home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Source Code / Zoners Half-Life Tools / hlrad / qrad.cpp < prev    next >
C/C++ Source or Header  |  2002-12-09  |  91KB  |  2,845 lines

  1. /*
  2.  
  3.     R A D I O S I T Y    -aka-    R A D 
  4.  
  5.     Code based on original code from Valve Software, 
  6.     Modified by Sean "Zoner" Cavanaugh (seanc@gearboxsoftware.com) with permission.
  7.     Modified by Tony "Merl" Moore (merlinis@bigpond.net.au) [AJM]
  8.     
  9. */
  10.  
  11. #ifdef SYSTEM_WIN32
  12. #define WIN32_LEAN_AND_MEAN
  13. #include <windows.h>
  14. #endif
  15.  
  16. #include <vector>
  17. #include <string>
  18.  
  19. #include "qrad.h"
  20.  
  21.  
  22. /*
  23.  * NOTES
  24.  * -----
  25.  * every surface must be divided into at least two g_patches each axis
  26.  */
  27.  
  28. typedef enum
  29. {
  30.     eMethodVismatrix,
  31.     eMethodSparseVismatrix,
  32.     eMethodNoVismatrix
  33. }
  34. eVisMethods;
  35.  
  36. eVisMethods     g_method = eMethodVismatrix;
  37.  
  38. vec_t           g_fade = DEFAULT_FADE;
  39. int             g_falloff = DEFAULT_FALLOFF;
  40.  
  41. patch_t*        g_face_patches[MAX_MAP_FACES];
  42. entity_t*       g_face_entity[MAX_MAP_FACES];
  43. eModelLightmodes g_face_lightmode[MAX_MAP_FACES];
  44. patch_t         g_patches[MAX_PATCHES];
  45. unsigned        g_num_patches;
  46.  
  47. #ifdef ZHLT_TEXLIGHT
  48. static vec3_t   emitlight[MAX_PATCHES][MAXLIGHTMAPS]; //LRC
  49. static vec3_t   addlight[MAX_PATCHES][MAXLIGHTMAPS]; //LRC
  50. #else
  51. static vec3_t   emitlight[MAX_PATCHES];
  52. static vec3_t   addlight[MAX_PATCHES];
  53. #endif
  54.  
  55. vec3_t          g_face_offset[MAX_MAP_FACES];              // for rotating bmodels
  56.  
  57. vec_t           g_direct_scale = DEFAULT_DLIGHT_SCALE;
  58.  
  59. unsigned        g_numbounce = DEFAULT_BOUNCE;              // 3; /* Originally this was 8 */
  60.  
  61. static bool     g_dumppatches = DEFAULT_DUMPPATCHES;
  62.  
  63. vec3_t          g_ambient = { DEFAULT_AMBIENT_RED, DEFAULT_AMBIENT_GREEN, DEFAULT_AMBIENT_BLUE };
  64. float           g_maxlight = DEFAULT_MAXLIGHT;             // 196  /* Originally this was 196 */
  65.  
  66. float           g_lightscale = DEFAULT_LIGHTSCALE;
  67. float           g_dlight_threshold = DEFAULT_DLIGHT_THRESHOLD;  // was DIRECT_LIGHT constant
  68.  
  69. char            g_source[_MAX_PATH] = "";
  70.  
  71. char            g_vismatfile[_MAX_PATH] = "";
  72. bool            g_incremental = DEFAULT_INCREMENTAL;
  73. #ifndef HLRAD_WHOME
  74. float           g_qgamma = DEFAULT_GAMMA;
  75. #endif
  76. float           g_indirect_sun = DEFAULT_INDIRECT_SUN;
  77. bool            g_extra = DEFAULT_EXTRA;
  78. bool            g_texscale = DEFAULT_TEXSCALE;
  79.  
  80. float           g_smoothing_threshold;
  81. float           g_smoothing_value = DEFAULT_SMOOTHING_VALUE;
  82.  
  83. bool            g_circus = DEFAULT_CIRCUS;
  84. bool            g_allow_opaques = DEFAULT_ALLOW_OPAQUES;
  85.  
  86. // --------------------------------------------------------------------------
  87. // Changes by Adam Foster - afoster@compsoc.man.ac.uk
  88. #ifdef HLRAD_WHOME
  89. vec3_t        g_colour_qgamma = { DEFAULT_COLOUR_GAMMA_RED, DEFAULT_COLOUR_GAMMA_GREEN, DEFAULT_COLOUR_GAMMA_BLUE };
  90. vec3_t        g_colour_lightscale = { DEFAULT_COLOUR_LIGHTSCALE_RED, DEFAULT_COLOUR_LIGHTSCALE_GREEN, DEFAULT_COLOUR_LIGHTSCALE_BLUE };
  91. vec3_t        g_colour_jitter_hack = { DEFAULT_COLOUR_JITTER_HACK_RED, DEFAULT_COLOUR_JITTER_HACK_GREEN, DEFAULT_COLOUR_JITTER_HACK_BLUE };
  92. vec3_t        g_jitter_hack = { DEFAULT_JITTER_HACK_RED, DEFAULT_JITTER_HACK_GREEN, DEFAULT_JITTER_HACK_BLUE };
  93. bool        g_diffuse_hack = DEFAULT_DIFFUSE_HACK;
  94. bool        g_spotlight_hack = DEFAULT_SPOTLIGHT_HACK;
  95. vec3_t        g_softlight_hack = { DEFAULT_SOFTLIGHT_HACK_RED, DEFAULT_SOFTLIGHT_HACK_GREEN, DEFAULT_SOFTLIGHT_HACK_BLUE };
  96. float        g_softlight_hack_distance = DEFAULT_SOFTLIGHT_HACK_DISTANCE;
  97. #endif
  98. // --------------------------------------------------------------------------
  99.  
  100. #ifdef HLRAD_HULLU
  101. bool        g_customshadow_with_bouncelight = DEFAULT_CUSTOMSHADOW_WITH_BOUNCELIGHT;
  102. bool        g_rgb_transfers = DEFAULT_RGB_TRANSFERS;
  103. #endif
  104.  
  105. // Cosine of smoothing angle(in radians)
  106. float           g_coring = DEFAULT_CORING;                 // Light threshold to force to blackness(minimizes lightmaps)
  107. bool            g_chart = DEFAULT_CHART;
  108. bool            g_estimate = DEFAULT_ESTIMATE;
  109. bool            g_info = DEFAULT_INFO;
  110.  
  111. #ifdef ZHLT_PROGRESSFILE // AJM
  112. char*           g_progressfile = DEFAULT_PROGRESSFILE; // "-progressfile path"
  113. #endif
  114.  
  115. // Patch creation and subdivision criteria
  116. bool            g_subdivide = DEFAULT_SUBDIVIDE;
  117. vec_t           g_chop = DEFAULT_CHOP;
  118. vec_t           g_texchop = DEFAULT_TEXCHOP;
  119.  
  120. // Opaque faces
  121. opaqueList_t*   g_opaque_face_list = NULL;
  122. unsigned        g_opaque_face_count = 0;
  123. unsigned        g_max_opaque_face_count = 0;               // Current array maximum (used for reallocs)
  124.  
  125. // Misc
  126. int             leafparents[MAX_MAP_LEAFS];
  127. int             nodeparents[MAX_MAP_NODES];
  128.  
  129. #ifdef ZHLT_INFO_COMPILE_PARAMETERS
  130. // =====================================================================================
  131. //  GetParamsFromEnt
  132. //      this function is called from parseentity when it encounters the 
  133. //      info_compile_parameters entity. each tool should have its own version of this
  134. //      to handle its own specific settings.
  135. // =====================================================================================
  136. void            GetParamsFromEnt(entity_t* mapent)
  137. {
  138.     int     iTmp;
  139.     float   flTmp;
  140.     const char* pszTmp;
  141.  
  142.     Log("\nCompile Settings detected from info_compile_parameters entity\n");
  143.  
  144.     // verbose(choices) : "Verbose compile messages" : 0 = [ 0 : "Off" 1 : "On" ]
  145.     iTmp = IntForKey(mapent, "verbose");
  146.     if (iTmp == 1)
  147.     {
  148.         g_verbose = true;
  149.     }
  150.     else if (iTmp == 0)
  151.     {
  152.         g_verbose = false;
  153.     }
  154.     Log("%30s [ %-9s ]\n", "Compile Option", "setting");
  155.     Log("%30s [ %-9s ]\n", "Verbose Compile Messages", g_verbose ? "on" : "off");
  156.  
  157.     // estimate(choices) :"Estimate Compile Times?" : 0 = [ 0: "Yes" 1: "No" ]
  158.     if (IntForKey(mapent, "estimate")) 
  159.     {
  160.         g_estimate = true;
  161.     }
  162.     else
  163.     {
  164.         g_estimate = false;
  165.     }
  166.     Log("%30s [ %-9s ]\n", "Estimate Compile Times", g_estimate ? "on" : "off");
  167.  
  168.     // priority(choices) : "Priority Level" : 0 = [    0 : "Normal" 1 : "High"    -1 : "Low" ]
  169.     if (!strcmp(ValueForKey(mapent, "priority"), "1"))
  170.     {
  171.         g_threadpriority = eThreadPriorityHigh;
  172.         Log("%30s [ %-9s ]\n", "Thread Priority", "high");
  173.     }
  174.     else if (!strcmp(ValueForKey(mapent, "priority"), "-1"))
  175.     {
  176.         g_threadpriority = eThreadPriorityLow;
  177.         Log("%30s [ %-9s ]\n", "Thread Priority", "low");
  178.     }
  179.  
  180.     // bounce(integer) : "Number of radiosity bounces" : 0 
  181.     iTmp = IntForKey(mapent, "bounce");
  182.     if (iTmp)
  183.     {
  184.         g_numbounce = abs(iTmp);
  185.         Log("%30s [ %-9s ]\n", "Number of radiosity bounces", ValueForKey(mapent, "bounce"));
  186.     }
  187.     
  188. #ifdef HLRAD_HULLU
  189.     iTmp = IntForKey(mapent, "customshadowwithbounce");
  190.     if (iTmp)
  191.     {  
  192.         g_customshadow_with_bouncelight = true;
  193.         Log("%30s [ %-9s ]\n", "Custom Shadow with Bounce Light", ValueForKey(mapent, "customshadowwithbounce"));
  194.     }
  195.     iTmp = IntForKey(mapent, "rgbtransfers");
  196.     if (iTmp)
  197.     {  
  198.         g_rgb_transfers = true;
  199.         Log("%30s [ %-9s ]\n", "RGB Transfers", ValueForKey(mapent, "rgbtransfers"));
  200.     }
  201. #endif
  202.  
  203.     // ambient(string) : "Ambient world light (0.0 to 1.0, R G B)" : "0 0 0" 
  204.     //vec3_t          g_ambient = { DEFAULT_AMBIENT_RED, DEFAULT_AMBIENT_GREEN, DEFAULT_AMBIENT_BLUE };
  205.     pszTmp = ValueForKey(mapent, "ambient");
  206.     if (pszTmp)
  207.     {
  208.         float red = 0, green = 0, blue = 0;
  209.         if (sscanf(pszTmp, "%f %f %f", &red, &green, &blue))
  210.         {
  211.             if (red < 0 || red > 1 || green < 0 || green > 1 || blue < 0 || blue > 1)
  212.             {
  213.                 Error("info_compile_parameters: Ambient World Light (ambient) all 3 values must be within the range of 0.0 to 1.0\n"
  214.                       "Parsed values:\n"
  215.                       "    red [ %1.3f ] %s\n"
  216.                       "  green [ %1.3f ] %s\n"
  217.                       "   blue [ %1.3f ] %s\n"
  218.                       , red,    (red   < 0 || red   > 1) ? "OUT OF RANGE" : ""
  219.                       , green,  (green < 0 || green > 1) ? "OUT OF RANGE" : ""
  220.                       , blue,   (blue  < 0 || blue  > 1) ? "OUT OF RANGE" : "" );
  221.             }
  222.  
  223.             if (red == 0 && green == 0 && blue == 0)
  224.             {} // dont bother setting null values
  225.             else
  226.             {
  227.                 g_ambient[0] = red * 128;
  228.                 g_ambient[1] = green * 128;
  229.                 g_ambient[2] = blue * 128;
  230.                 Log("%30s [ %1.3f %1.3f %1.3f ]\n", "Ambient world light (R G B)", red, green, blue);
  231.             }
  232.         }
  233.         else
  234.         {
  235.             Error("info_compile_parameters: Ambient World Light (ambient) has unrecognised value\n"
  236.                   "This keyvalue accepts 3 numeric values from 0.000 to 1.000, use \"0 0 0\" if in doubt");
  237.         }
  238.     }
  239.  
  240.     // smooth(integer) : "Smoothing threshold (in degrees)" : 0 
  241.     flTmp = FloatForKey(mapent, "smooth");
  242.     if (flTmp)
  243.     {
  244.         g_smoothing_threshold = flTmp;
  245.         Log("%30s [ %-9s ]\n", "Smoothing threshold", ValueForKey(mapent, "smooth"));
  246.     }
  247.  
  248.     // dscale(integer) : "Direct Lighting Scale" : 1 
  249.     flTmp = FloatForKey(mapent, "dscale");
  250.     if (flTmp)
  251.     {
  252.         g_direct_scale = flTmp;
  253.         Log("%30s [ %-9s ]\n", "Direct Lighting Scale", ValueForKey(mapent, "dscale"));
  254.     }
  255.  
  256.     // chop(integer) : "Chop Size" : 64 
  257.     iTmp = IntForKey(mapent, "chop");
  258.     if (iTmp)
  259.     {
  260.         g_chop = iTmp;
  261.         Log("%30s [ %-9s ]\n", "Chop Size", ValueForKey(mapent, "chop"));
  262.     }
  263.  
  264.     // texchop(integer) : "Texture Light Chop Size" : 32 
  265.     flTmp = FloatForKey(mapent, "texchop");
  266.     if (flTmp)
  267.     {
  268.         g_texchop = flTmp;
  269.         Log("%30s [ %-9s ]\n", "Texture Light Chop Size", ValueForKey(mapent, "texchop"));
  270.     }
  271.  
  272.     /* 
  273.     hlrad(choices) : "HLRAD" : 0 =
  274.     [
  275.         0 : "Off"
  276.         1 : "Normal"
  277.         2 : "Extra"
  278.     ]
  279.     */
  280.     iTmp = IntForKey(mapent, "hlrad");
  281.     if (iTmp == 0)
  282.     {
  283.         Fatal(assume_TOOL_CANCEL, 
  284.             "%s flag was not checked in info_compile_parameters entity, execution of %s cancelled", g_Program, g_Program);
  285.         CheckFatal();  
  286.     }
  287.     else if (iTmp == 1)
  288.     {
  289.         g_extra = false;
  290.     }
  291.     else if (iTmp == 2)
  292.     {
  293.         g_extra = true;
  294.     }
  295.     Log("%30s [ %-9s ]\n", "Extra RAD", g_extra ? "on" : "off");
  296.  
  297.     /*
  298.     sparse(choices) : "Vismatrix Method" : 2 =
  299.     [
  300.         0 : "No Vismatrix"
  301.         1 : "Sparse Vismatrix"
  302.         2 : "Normal"
  303.     ]
  304.     */
  305.     iTmp = IntForKey(mapent, "sparse");
  306.     if (iTmp == 1)
  307.     {
  308.         g_method = eMethodSparseVismatrix;
  309.     }
  310.     else if (iTmp == 0)
  311.     {
  312.         g_method = eMethodNoVismatrix;
  313.     }
  314.     else if (iTmp == 2)
  315.     {
  316.         g_method = eMethodVismatrix;
  317.     }
  318.     Log("%30s [ %-9s ]\n", "Sparse Vismatrix",  g_method == eMethodSparseVismatrix ? "on" : "off");
  319.     Log("%30s [ %-9s ]\n", "NoVismatrix",  g_method == eMethodNoVismatrix ? "on" : "off");
  320.  
  321.     /*
  322.     circus(choices) : "Circus RAD lighting" : 0 =
  323.     [
  324.         0 : "Off"
  325.         1 : "On"
  326.     ]
  327.     */
  328.     iTmp = IntForKey(mapent, "circus");
  329.     if (iTmp == 0)
  330.     {
  331.         g_circus = false;
  332.     }
  333.     else if (iTmp == 1)
  334.     {
  335.         g_circus = true;
  336.     }
  337.  
  338.     Log("%30s [ %-9s ]\n", "Circus Lighting Mode", g_circus ? "on" : "off");
  339.  
  340.     ////////////////////
  341.     Log("\n");
  342. }
  343. #endif
  344.  
  345. // =====================================================================================
  346. //  MakeParents
  347. //      blah
  348. // =====================================================================================
  349. static void     MakeParents(const int nodenum, const int parent)
  350. {
  351.     int             i;
  352.     int             j;
  353.     dnode_t*        node;
  354.  
  355.     nodeparents[nodenum] = parent;
  356.     node = g_dnodes + nodenum;
  357.  
  358.     for (i = 0; i < 2; i++)
  359.     {
  360.         j = node->children[i];
  361.         if (j < 0)
  362.         {
  363.             leafparents[-j - 1] = nodenum;
  364.         }
  365.         else
  366.         {
  367.             MakeParents(j, nodenum);
  368.         }
  369.     }
  370. }
  371.  
  372. // =====================================================================================
  373. //
  374. //    TEXTURE LIGHT VALUES
  375. //
  376. // =====================================================================================
  377.  
  378. // misc
  379. typedef struct
  380. {
  381.     std::string     name;
  382.     vec3_t          value;
  383.     const char*     filename;
  384. }
  385. texlight_t;
  386.  
  387. static std::vector< texlight_t > s_texlights;
  388. typedef std::vector< texlight_t >::iterator texlight_i;
  389.  
  390. // =====================================================================================
  391. //  ReadLightFile
  392. // =====================================================================================
  393. static void     ReadLightFile(const char* const filename)
  394. {
  395.     FILE*           f;
  396.     char            scan[MAXTOKEN];
  397.     short           argCnt;
  398.     unsigned int    file_texlights = 0;
  399.  
  400.     f = fopen(filename, "r");
  401.     if (!f)
  402.     {
  403.         Warning("Could not open texlight file %s", filename);
  404.         return;
  405.     }
  406.     else
  407.     {
  408.         Log("[Reading texlights from '%s']\n", filename);
  409.     }
  410.  
  411.     while (fgets(scan, sizeof(scan), f))
  412.     {
  413.         char*           comment;
  414.         char            szTexlight[_MAX_PATH];
  415.         vec_t           r, g, b, i = 1;
  416.  
  417.         comment = strstr(scan, "//");
  418.         if (comment)
  419.         {
  420.             // Newline and Null terminate the string early if there is a c++ style single line comment
  421.             comment[0] = '\n';
  422.             comment[1] = 0;
  423.         }
  424.  
  425.         argCnt = sscanf(scan, "%s %f %f %f %f", szTexlight, &r, &g, &b, &i);
  426.  
  427.         if (argCnt == 2)
  428.         {
  429.             // With 1+1 args, the R,G,B values are all equal to the first value
  430.             g = b = r;
  431.         }
  432.         else if (argCnt == 5)
  433.         {
  434.             // With 1+4 args, the R,G,B values are "scaled" by the fourth numeric value i;
  435.             r *= i / 255.0;
  436.             g *= i / 255.0;
  437.             b *= i / 255.0;
  438.         }
  439.         else if (argCnt != 4)
  440.         {
  441.             if (strlen(scan) > 4)
  442.             {
  443.                 Warning("ignoring bad texlight '%s' in %s", scan, filename);
  444.             }
  445.             continue;
  446.         }
  447.  
  448.         texlight_i it;
  449.         for (it = s_texlights.begin(); it != s_texlights.end(); it++)
  450.         {
  451.             if (strcmp(it->name.c_str(), szTexlight) == 0)
  452.             {
  453.                 if (strcmp(it->filename, filename) == 0)
  454.                 {
  455.                     Warning("Duplication of texlight '%s' in file '%s'!", it->name.c_str(), it->filename);
  456.                 }
  457.                 else if (it->value[0] != r || it->value[1] != g || it->value[2] != b)
  458.                 {
  459.                     Warning("Overriding '%s' from '%s' with '%s'!", it->name.c_str(), it->filename, filename);
  460.                 }
  461.                 else
  462.                 {
  463.                     Warning("Redundant '%s' def in '%s' AND '%s'!", it->name.c_str(), it->filename, filename);
  464.                 }
  465.                 s_texlights.erase(it);
  466.                 break;
  467.             }
  468.         }
  469.  
  470.         texlight_t      texlight;
  471.         texlight.name = szTexlight;
  472.         texlight.value[0] = r;
  473.         texlight.value[1] = g;
  474.         texlight.value[2] = b;
  475.         texlight.filename = filename;
  476.         file_texlights++;
  477.         s_texlights.push_back(texlight);
  478.     }
  479.     Log("[%u texlights parsed from '%s']\n\n", file_texlights, filename);
  480. }
  481.  
  482. // =====================================================================================
  483. //  LightForTexture
  484. // =====================================================================================
  485. static void     LightForTexture(const char* const name, vec3_t result)
  486. {
  487.     texlight_i it;
  488.     for (it = s_texlights.begin(); it != s_texlights.end(); it++)
  489.     {
  490.         if (!strcasecmp(name, it->name.c_str()))
  491.         {
  492.             VectorCopy(it->value, result);
  493.             return;
  494.         }
  495.     }
  496.     VectorClear(result);
  497. }
  498.  
  499.  
  500. // =====================================================================================
  501. //
  502. //    MAKE FACES
  503. //
  504. // =====================================================================================
  505.  
  506. // =====================================================================================
  507. //  BaseLightForFace
  508. // =====================================================================================
  509. static void     BaseLightForFace(const dface_t* const f, vec3_t light)
  510. {
  511.     texinfo_t*      tx;
  512.     miptex_t*       mt;
  513.     int             ofs;
  514.  
  515.     //
  516.     // check for light emited by texture
  517.     //
  518.     tx = &g_texinfo[f->texinfo];
  519.  
  520.     ofs = ((dmiptexlump_t*)g_dtexdata)->dataofs[tx->miptex];
  521.     mt = (miptex_t*)((byte*) g_dtexdata + ofs);
  522.  
  523.     LightForTexture(mt->name, light);
  524. }
  525.  
  526. // =====================================================================================
  527. //  IsSpecial
  528. // =====================================================================================
  529. static bool     IsSpecial(const dface_t* const f)
  530. {
  531.     return g_texinfo[f->texinfo].flags & TEX_SPECIAL;
  532. }
  533.  
  534. // =====================================================================================
  535. //  PlacePatchInside
  536. // =====================================================================================
  537. static bool     PlacePatchInside(patch_t* patch)
  538. {
  539.     const dplane_t* plane;
  540.     const vec_t*    face_offset = g_face_offset[patch->faceNumber];
  541.  
  542.     plane = getPlaneFromFaceNumber(patch->faceNumber);
  543.  
  544.     if (!HuntForWorld(patch->origin, face_offset, plane, 11, 0.1, 0.01) &&
  545.         !HuntForWorld(patch->origin, face_offset, plane, 11, 0.1, 0.1) &&
  546.         !HuntForWorld(patch->origin, face_offset, plane, 11, 0.1, 0.5) &&
  547.         !HuntForWorld(patch->origin, face_offset, plane, 11, 0.1, -0.01) &&
  548.         !HuntForWorld(patch->origin, face_offset, plane, 11, 0.1, -0.1))
  549.     {
  550.         // Try offsetting it by the plane normal (1 unit away) and try again
  551.  
  552.         VectorAdd(plane->normal, patch->origin, patch->origin); // Original offset-into-world method
  553.         if (PointInLeaf(patch->origin) == g_dleafs)
  554.         {
  555.             if (!HuntForWorld(patch->origin, face_offset, plane, 11, 0.1, 0.01) &&
  556.                 !HuntForWorld(patch->origin, face_offset, plane, 11, 0.1, 0.1) &&
  557.                 !HuntForWorld(patch->origin, face_offset, plane, 11, 0.1, 0.5) &&
  558.                 !HuntForWorld(patch->origin, face_offset, plane, 11, 0.1, -0.01) &&
  559.                 !HuntForWorld(patch->origin, face_offset, plane, 11, 0.1, -0.1))
  560.             {
  561.                 patch->flags = (ePatchFlags)(patch->flags | ePatchFlagOutside);
  562.                 Developer(DEVELOPER_LEVEL_MESSAGE, "Patch @ (%4.3f %4.3f %4.3f) outside world\n",
  563.                           patch->origin[0], patch->origin[1], patch->origin[2]);
  564.                 return false;
  565.             }
  566.         }
  567.     }
  568.  
  569.     return true;
  570. }
  571.  
  572.  
  573. // =====================================================================================
  574. //
  575. //    SUBDIVIDE PATCHES
  576. //
  577. // =====================================================================================
  578.  
  579. // misc
  580. #define MAX_SUBDIVIDE 16384
  581. static Winding* windingArray[MAX_SUBDIVIDE];
  582. static unsigned g_numwindings = 0;
  583.  
  584. // =====================================================================================
  585. //  AddWindingToArray
  586. // =====================================================================================
  587. static void     AddWindingToArray(Winding* winding)
  588. {
  589.     unsigned        x;
  590.  
  591.     Winding**       wA = windingArray;
  592.  
  593.     for (x = 0; x < g_numwindings; x++, wA++)
  594.     {
  595.         if (*wA == winding)
  596.         {
  597.             return;
  598.         }
  599.     }
  600.  
  601.     windingArray[g_numwindings++] = winding;
  602. }
  603.  
  604. static void     CreateStrips_r(Winding* winding, const vec3_t plane_normal, const vec_t plane_dist, vec_t step)
  605. {
  606.     Winding*        A;
  607.     Winding*        B;
  608.     vec_t           areaA;
  609.     vec_t           areaB;
  610.  
  611.     winding->Clip(plane_normal, plane_dist + step, &A, &B);
  612.  
  613.     if (A && B)
  614.     {
  615.         areaA = A->getArea();
  616.         areaB = B->getArea();
  617.         if ((areaA > 1.0) && (areaB > 1.0))
  618.         {
  619.             delete winding;
  620.             CreateStrips_r(A, plane_normal, plane_dist + step, step);
  621.             CreateStrips_r(B, plane_normal, plane_dist + step, step);
  622.             return;
  623.         }
  624.     }
  625.     else
  626.     {                                                      // Try the other direction
  627.         if (A)
  628.         {
  629.             delete A;
  630.         }
  631.         if (B)
  632.         {
  633.             delete B;
  634.         }
  635.  
  636.         winding->Clip(plane_normal, plane_dist - step, &A, &B);
  637.  
  638.         if (A && B)
  639.         {
  640.             areaA = A->getArea();
  641.             areaB = B->getArea();
  642.             if ((areaA > 1.0) && (areaB > 1.0))
  643.             {
  644.                 delete winding;
  645.                 CreateStrips_r(A, plane_normal, plane_dist - step, step);
  646.                 CreateStrips_r(B, plane_normal, plane_dist - step, step);
  647.                 return;
  648.             }
  649.         }
  650.     }
  651.  
  652.     // Last recursion, save it into the list
  653.     if (A)
  654.     {
  655.         delete A;
  656.     }
  657.     if (B)
  658.     {
  659.         delete B;
  660.     }
  661.  
  662.     AddWindingToArray(winding);
  663.     hlassume(g_numwindings < MAX_SUBDIVIDE, assume_GENERIC);
  664. }
  665.  
  666. // =====================================================================================
  667. //  CreateStrips
  668. // =====================================================================================
  669. static bool     CreateStrips(Winding* winding, const dplane_t* plane, vec_t step)
  670. {
  671.     Winding*        A;
  672.     Winding*        B;
  673.     vec_t           areaA;
  674.     vec_t           areaB;
  675.  
  676.     winding->Clip(plane->normal, plane->dist, &A, &B);
  677.  
  678.     if (A && B)
  679.     {
  680.         areaA = A->getArea();
  681.         areaB = B->getArea();
  682.         if ((areaA > 1.0) && (areaB > 1.0))
  683.         {
  684.             CreateStrips_r(A, (vec_t*)plane->normal, plane->dist, step);
  685.             CreateStrips_r(B, (vec_t*)plane->normal, plane->dist, step);
  686.             return true;
  687.         }
  688.     }
  689.  
  690.     if (A)
  691.     {
  692.         delete A;
  693.     }
  694.     if (B)
  695.     {
  696.         delete B;
  697.     }
  698.  
  699.     AddWindingToArray(winding);
  700.     hlassume(g_numwindings < MAX_SUBDIVIDE, assume_GENERIC);
  701.     return false;
  702. }
  703.  
  704. // =====================================================================================
  705. //  cutWindingWithGrid
  706. //      Caller must free this returned value at some point
  707. // =====================================================================================
  708. static void     cutWindingWithGrid(patch_t* patch, const dplane_t* const plA, const dplane_t* const plB)
  709. {
  710.     Winding**       winding;
  711.     unsigned int    count;
  712.     unsigned int    x;
  713.  
  714.     g_numwindings = 0;
  715.     if (CreateStrips(patch->winding, plA, patch->chop))
  716.     {
  717.         delete patch->winding;
  718.         patch->winding = NULL;                             // Invalidated by CreateStrips routine
  719.     }
  720.     count = g_numwindings;
  721.  
  722.     for (x = 0, winding = windingArray; x < count; x++, winding++)
  723.     {
  724.         if (CreateStrips(*winding, plB, patch->chop))
  725.         {
  726.             delete *winding;
  727.             *winding = NULL;
  728.         }
  729.     }
  730. }
  731.  
  732. // =====================================================================================
  733. //  getGridPlanes
  734. //      From patch, determine perpindicular grid planes to subdivide with (returned in planeA and planeB)
  735. //      assume S and T is perpindicular (they SHOULD be in worldcraft 3.3 but aren't always . . .)
  736. // =====================================================================================
  737. static void     getGridPlanes(const patch_t* const p, dplane_t* const pl)
  738. {
  739.     const patch_t*  patch = p;
  740.     dplane_t*       planes = pl;
  741.     const dface_t*  f = g_dfaces + patch->faceNumber;
  742.     texinfo_t*      tx = &g_texinfo[f->texinfo];
  743.     dplane_t*       plane = planes;
  744.     const dplane_t* faceplane = getPlaneFromFaceNumber(patch->faceNumber);
  745.     int             x;
  746.  
  747.     for (x = 0; x < 2; x++, plane++)
  748.     {
  749.         vec3_t          a, b, c;
  750.         vec3_t          delta1, delta2;
  751.  
  752.         VectorCopy(patch->origin, a);
  753.         VectorAdd(patch->origin, faceplane->normal, b);
  754.         VectorAdd(patch->origin, tx->vecs[x], c);
  755.  
  756.         VectorSubtract(b, a, delta1);
  757.         VectorSubtract(c, a, delta2);
  758.  
  759.         CrossProduct(delta1, delta2, plane->normal);
  760.         VectorNormalize(plane->normal);
  761.         plane->dist = DotProduct(plane->normal, patch->origin);
  762.     }
  763. }
  764.  
  765. // =====================================================================================
  766. //  SubdividePatch
  767. // =====================================================================================
  768. static void     SubdividePatch(patch_t* patch)
  769. {
  770.     dplane_t        planes[2];
  771.     dplane_t*       plA = &planes[0];
  772.     dplane_t*       plB = &planes[1];
  773.     Winding**       winding;
  774.     unsigned        x;
  775.     patch_t*        new_patch;
  776.  
  777.     memset(windingArray, 0, sizeof(windingArray));
  778.     g_numwindings = 0;
  779.  
  780.     getGridPlanes(patch, planes);
  781.     cutWindingWithGrid(patch, plA, plB);
  782.  
  783.     x = 0;
  784.     patch->next = NULL;
  785.     winding = windingArray;
  786.     while (*winding == NULL)
  787.     {
  788.         winding++;
  789.         x++;
  790.     }
  791.     patch->winding = *winding;
  792.     winding++;
  793.     x++;
  794.     patch->area = patch->winding->getArea();
  795.     patch->winding->getCenter(patch->origin);
  796.     PlacePatchInside(patch);
  797.  
  798.     new_patch = g_patches + g_num_patches;
  799.     for (; x < g_numwindings; x++, winding++)
  800.     {
  801.         if (*winding)
  802.         {
  803.             memcpy(new_patch, patch, sizeof(patch_t));
  804.  
  805.             new_patch->winding = *winding;
  806.             new_patch->area = new_patch->winding->getArea();
  807.             new_patch->winding->getCenter(new_patch->origin);
  808.             PlacePatchInside(new_patch);
  809.  
  810.             new_patch++;
  811.             g_num_patches++;
  812.             hlassume(g_num_patches < MAX_PATCHES, assume_MAX_PATCHES);
  813.         }
  814.     }
  815.  
  816.     // ATTENTION: We let SortPatches relink all the ->next correctly! instead of doing it here too which is somewhat complicated
  817. }
  818.  
  819. // =====================================================================================
  820. //  MakePatchForFace
  821. static float    totalarea = 0;
  822. // =====================================================================================
  823. static vec_t    getScale(const patch_t* const patch)
  824. {
  825.     dface_t*        f = g_dfaces + patch->faceNumber;
  826.     texinfo_t*      tx = &g_texinfo[f->texinfo];
  827.  
  828.     if (g_texscale)
  829.     {
  830.         vec_t           scale[2];
  831.  
  832.         scale[0] = 0.0;
  833.         scale[1] = 0.0;
  834.  
  835.         scale[0] += tx->vecs[0][0] * tx->vecs[0][0];
  836.         scale[0] += tx->vecs[0][1] * tx->vecs[0][1];
  837.         scale[0] += tx->vecs[0][2] * tx->vecs[0][2];
  838.  
  839.         scale[1] += tx->vecs[1][0] * tx->vecs[1][0];
  840.         scale[1] += tx->vecs[1][1] * tx->vecs[1][1];
  841.         scale[1] += tx->vecs[1][2] * tx->vecs[1][2];
  842.  
  843.         scale[0] = sqrt(scale[0]);
  844.         scale[1] = sqrt(scale[1]);
  845.  
  846.         return 2.0 / ((scale[0] + scale[1]));
  847.     }
  848.     else
  849.     {
  850.         return 1.0;
  851.     }
  852. }
  853.  
  854. // =====================================================================================
  855. //  getChop
  856. // =====================================================================================
  857. static vec_t    getChop(const patch_t* const patch)
  858. {
  859.     vec_t           rval;
  860.  
  861.     if (VectorCompare(patch->baselight, vec3_origin))
  862.     {
  863.         rval = g_chop * getScale(patch);
  864.     }
  865.     else
  866.     {
  867.         rval = g_texchop * getScale(patch);
  868.         if (g_extra)
  869.         {
  870.             rval *= 0.5;
  871.         }
  872.     }
  873.  
  874.     return rval;
  875. }
  876.  
  877. // =====================================================================================
  878. //  MakePatchForFace
  879. // =====================================================================================
  880. #ifdef ZHLT_TEXLIGHT
  881. static void     MakePatchForFace(const int fn, Winding* w, int style) //LRC
  882. #else
  883. static void     MakePatchForFace(const int fn, Winding* w)
  884. #endif
  885. {
  886.     const dface_t*  f = g_dfaces + fn;
  887.  
  888.     // No g_patches at all for the sky!
  889.     if (!IsSpecial(f))
  890.     {
  891.         patch_t*        patch;
  892.         vec3_t          light;
  893.         vec3_t          centroid = { 0, 0, 0 };
  894.  
  895.         int             numpoints = w->m_NumPoints;
  896.  
  897.         if (numpoints < 3)                                 // WTF! (Actually happens in real-world maps too)
  898.         {
  899.             Developer(DEVELOPER_LEVEL_WARNING, "Face %d only has %d points on winding\n", fn, numpoints);
  900.             return;
  901.         }
  902.         if (numpoints > MAX_POINTS_ON_WINDING)
  903.         {
  904.             Error("numpoints %d > MAX_POINTS_ON_WINDING", numpoints);
  905.             return;
  906.         }
  907.  
  908.         patch = &g_patches[g_num_patches];
  909.         hlassume(g_num_patches < MAX_PATCHES, assume_MAX_PATCHES);
  910.         memset(patch, 0, sizeof(patch_t));
  911.  
  912.         patch->winding = w;
  913.  
  914.         patch->area = patch->winding->getArea();
  915.         patch->winding->getCenter(patch->origin);
  916.         patch->faceNumber = fn;
  917.  
  918.         totalarea += patch->area;
  919.  
  920.         PlacePatchInside(patch);
  921.  
  922.         BaseLightForFace(f, light);
  923. #ifdef ZHLT_TEXLIGHT
  924.         //LRC        VectorCopy(light, patch->totallight);
  925. #else
  926.         VectorCopy(light, patch->totallight);
  927. #endif
  928.         VectorCopy(light, patch->baselight);
  929.  
  930. #ifdef ZHLT_TEXLIGHT
  931.         //LRC
  932.         int i;
  933.         patch->totalstyle[0] = 0;
  934.         for (i = 1; i < MAXLIGHTMAPS; i++)
  935.         {
  936.             patch->totalstyle[i] = 255;
  937.         }
  938.         if (style)
  939.         {
  940.             patch->emitstyle = patch->totalstyle[1] = style;
  941.         }
  942.         //LRC (ends)
  943. #endif
  944.  
  945.         patch->scale = getScale(patch);
  946.         patch->chop = getChop(patch);
  947.  
  948.         g_face_patches[fn] = patch;
  949.         g_num_patches++;
  950.  
  951.         // Per-face data
  952.         {
  953.             int             j;
  954.  
  955.             // Centroid of face for nudging samples in direct lighting pass
  956.             for (j = 0; j < f->numedges; j++)
  957.             {
  958.                 int             edge = g_dsurfedges[f->firstedge + j];
  959.  
  960.                 if (edge > 0)
  961.                 {
  962.                     VectorAdd(g_dvertexes[g_dedges[edge].v[0]].point, centroid, centroid);
  963.                     VectorAdd(g_dvertexes[g_dedges[edge].v[1]].point, centroid, centroid);
  964.                 }
  965.                 else
  966.                 {
  967.                     VectorAdd(g_dvertexes[g_dedges[-edge].v[1]].point, centroid, centroid);
  968.                     VectorAdd(g_dvertexes[g_dedges[-edge].v[0]].point, centroid, centroid);
  969.                 }
  970.             }
  971.  
  972.             // Fixup centroid for anything with an altered origin (rotating models/turrets mostly)
  973.             // Save them for moving direct lighting points towards the face center
  974.             VectorScale(centroid, 1.0 / (f->numedges * 2), centroid);
  975.             VectorAdd(centroid, g_face_offset[fn], g_face_centroids[fn]);
  976.         }
  977.  
  978.         {
  979.             vec3_t          mins;
  980.             vec3_t          maxs;
  981.  
  982.             patch->winding->getBounds(mins, maxs);
  983.  
  984.             if (g_subdivide)
  985.             {
  986.                 vec_t           amt;
  987.                 vec_t           length;
  988.                 vec3_t          delta;
  989.  
  990.                 VectorSubtract(maxs, mins, delta);
  991.                 length = VectorLength(delta);
  992.                 if (VectorCompare(patch->baselight, vec3_origin))
  993.                 {
  994.                     amt = g_chop;
  995.                 }
  996.                 else
  997.                 {
  998.                     amt = g_texchop;
  999.                 }
  1000.  
  1001.                 if (length > amt)
  1002.                 {
  1003.                     if (patch->area < 1.0)
  1004.                     {
  1005.                         Developer(DEVELOPER_LEVEL_WARNING,
  1006.                                   "Patch at (%4.3f %4.3f %4.3f) (face %d) tiny area (%4.3f) not subdividing \n",
  1007.                                   patch->origin[0], patch->origin[1], patch->origin[2], patch->faceNumber, patch->area);
  1008.                     }
  1009.                     else
  1010.                     {
  1011.                         SubdividePatch(patch);
  1012.                     }
  1013.                 }
  1014.             }
  1015.         }
  1016.     }
  1017. }
  1018.  
  1019. // =====================================================================================
  1020. //  AddFaceToOpaqueList
  1021. // =====================================================================================
  1022. #ifdef HLRAD_HULLU
  1023. static void     AddFaceToOpaqueList(const unsigned facenum, const Winding* const winding, const vec3_t &transparency_scale, const bool transparency)
  1024. #else
  1025. static void     AddFaceToOpaqueList(const unsigned facenum, const Winding* const winding)
  1026. #endif
  1027. {
  1028.     if (g_opaque_face_count == g_max_opaque_face_count)
  1029.     {
  1030.         g_max_opaque_face_count += OPAQUE_ARRAY_GROWTH_SIZE;
  1031.         g_opaque_face_list = (opaqueList_t*)realloc(g_opaque_face_list, sizeof(opaqueList_t) * g_max_opaque_face_count);
  1032.     }
  1033.  
  1034.     {
  1035.         opaqueList_t*   opaque = &g_opaque_face_list[g_opaque_face_count];
  1036.  
  1037.         g_opaque_face_count++;
  1038.  
  1039. #ifdef HLRAD_HULLU
  1040.         VectorCopy(transparency_scale, opaque->transparency_scale);
  1041.         opaque->transparency = transparency;
  1042. #endif
  1043.         opaque->facenum = facenum;
  1044.         getAdjustedPlaneFromFaceNumber(facenum, &opaque->plane);
  1045.         opaque->winding = new Winding(*winding);
  1046.     }
  1047. }
  1048.  
  1049. // =====================================================================================
  1050. //  FreeOpaqueFaceList
  1051. // =====================================================================================
  1052. static void     FreeOpaqueFaceList()
  1053. {
  1054.     unsigned        x;
  1055.     opaqueList_t*   opaque = g_opaque_face_list;
  1056.  
  1057.     for (x = 0; x < g_opaque_face_count; x++, opaque++)
  1058.     {
  1059.         delete opaque->winding;
  1060.         opaque->winding = NULL;
  1061.     }
  1062.     free(g_opaque_face_list);
  1063.  
  1064.     g_opaque_face_list = NULL;
  1065.     g_opaque_face_count = 0;
  1066.     g_max_opaque_face_count = 0;
  1067. }
  1068.  
  1069. // =====================================================================================
  1070. //  MakePatches
  1071. // =====================================================================================
  1072. static void     MakePatches()
  1073. {
  1074.     int             i;
  1075.     int             j;
  1076.     unsigned int    k;
  1077.     dface_t*        f;
  1078.     int             fn;
  1079.     Winding*        w;
  1080.     dmodel_t*       mod;
  1081.     vec3_t          origin;
  1082.     entity_t*       ent;
  1083.     const char*     s;
  1084.     vec3_t          light_origin;
  1085.     vec3_t          model_center;
  1086.     bool            b_light_origin;
  1087.     bool            b_model_center;
  1088.     eModelLightmodes lightmode;
  1089.  
  1090. #ifdef ZHLT_TEXLIGHT
  1091.     int                style; //LRC
  1092. #endif
  1093.  
  1094. #ifdef HLRAD_HULLU
  1095.     vec3_t        d_transparency;
  1096.     bool        b_transparency;
  1097. #endif
  1098.  
  1099.     Log("%i faces\n", g_numfaces);
  1100.  
  1101.     Log("Create Patches : ");
  1102.  
  1103.     for (i = 0; i < g_nummodels; i++)
  1104.     {
  1105.         b_light_origin = false;
  1106.         b_model_center = false;
  1107.         lightmode = eModelLightmodeNull;
  1108.  
  1109. #ifdef HLRAD_OPACITY // AJM
  1110.         float         l_opacity = 0.0f; // decimal percentage 
  1111. #endif
  1112.  
  1113.         mod = g_dmodels + i;
  1114.         ent = EntityForModel(i);
  1115.         VectorCopy(vec3_origin, origin);
  1116.  
  1117.         if (*(s = ValueForKey(ent, "zhlt_lightflags")))
  1118.         {
  1119.             lightmode = (eModelLightmodes)atoi(s);
  1120.         }
  1121.  
  1122.         // models with origin brushes need to be offset into their in-use position
  1123.         if (*(s = ValueForKey(ent, "origin")))
  1124.         {
  1125.             double          v1, v2, v3;
  1126.  
  1127.             if (sscanf(s, "%lf %lf %lf", &v1, &v2, &v3) == 3)
  1128.             {
  1129.                 origin[0] = v1;
  1130.                 origin[1] = v2;
  1131.                 origin[2] = v3;
  1132.             }
  1133.  
  1134.         }
  1135.  
  1136.         // Allow models to be lit in an alternate location (pt1)
  1137.         if (*(s = ValueForKey(ent, "light_origin")))
  1138.         {
  1139.             entity_t*       e = FindTargetEntity(s);
  1140.  
  1141.             if (e)
  1142.             {
  1143.                 if (*(s = ValueForKey(e, "origin")))
  1144.                 {
  1145.                     double          v1, v2, v3;
  1146.  
  1147.                     if (sscanf(s, "%lf %lf %lf", &v1, &v2, &v3) == 3)
  1148.                     {
  1149.                         light_origin[0] = v1;
  1150.                         light_origin[1] = v2;
  1151.                         light_origin[2] = v3;
  1152.  
  1153.                         b_light_origin = true;
  1154.                     }
  1155.                 }
  1156.             }
  1157.         }
  1158.  
  1159.         // Allow models to be lit in an alternate location (pt2)
  1160.         if (*(s = ValueForKey(ent, "model_center")))
  1161.         {
  1162.             double          v1, v2, v3;
  1163.  
  1164.             if (sscanf(s, "%lf %lf %lf", &v1, &v2, &v3) == 3)
  1165.             {
  1166.                 model_center[0] = v1;
  1167.                 model_center[1] = v2;
  1168.                 model_center[2] = v3;
  1169.  
  1170.                 b_model_center = true;
  1171.             }
  1172.         }
  1173.  
  1174. #ifdef HLRAD_HULLU
  1175.     // Check for colored transparency/custom shadows
  1176.         VectorFill(d_transparency, 1.0);
  1177.         b_transparency = false;
  1178.         
  1179.         if (*(s = ValueForKey(ent, "zhlt_customshadow")))
  1180.         {
  1181.             double r1 = 1.0, g1 = 1.0, b1 = 1.0, tmp = 1.0;
  1182.             if (sscanf(s, "%lf %lf %lf", &r1, &g1, &b1) == 3) //RGB version
  1183.             {
  1184.                 if(r1<0.0) r1 = 0.0;
  1185.                 if(g1<0.0) g1 = 0.0;
  1186.                 if(b1<0.0) b1 = 0.0;
  1187.                 
  1188.                 d_transparency[0] = r1;
  1189.                 d_transparency[1] = g1;
  1190.                 d_transparency[2] = b1;
  1191.                 b_transparency = true;
  1192.             }
  1193.             else if (sscanf(s, "%lf", &tmp) == 1) //Greyscale version
  1194.             {
  1195.                 if(tmp<0.0) tmp = 0.0;
  1196.                 
  1197.                 VectorFill(d_transparency, tmp);
  1198.                 b_transparency = true;
  1199.             }
  1200.         }
  1201. #endif
  1202.         // Allow models to be lit in an alternate location (pt3)
  1203.         if (b_light_origin && b_model_center)
  1204.         {
  1205.             VectorSubtract(light_origin, model_center, origin);
  1206.         }
  1207.  
  1208. #ifdef ZHLT_TEXLIGHT        
  1209.         //LRC:
  1210.         if (*(s = ValueForKey(ent, "style")))
  1211.         {
  1212.             style = atoi(s);
  1213.             if (style < 0)
  1214.                 style = -style;
  1215.         }
  1216.         else
  1217.         {
  1218.             style = 0;
  1219.         }
  1220.         //LRC (ends)
  1221. #endif
  1222.  
  1223.         for (j = 0; j < mod->numfaces; j++)
  1224.         {
  1225.             fn = mod->firstface + j;
  1226.             g_face_entity[fn] = ent;
  1227.             VectorCopy(origin, g_face_offset[fn]);
  1228.             g_face_lightmode[fn] = lightmode;
  1229.             f = g_dfaces + fn;
  1230.             w = new Winding(*f);
  1231.             for (k = 0; k < w->m_NumPoints; k++)
  1232.             {
  1233.                 VectorAdd(w->m_Points[k], origin, w->m_Points[k]);
  1234.             }
  1235.             if (g_allow_opaques)
  1236.             {
  1237.                 if (lightmode & eModelLightmodeOpaque)
  1238.                 {
  1239. #ifdef HLRAD_HULLU
  1240.                     AddFaceToOpaqueList(fn, w, d_transparency, b_transparency); 
  1241. #else
  1242.                     AddFaceToOpaqueList(fn, w); 
  1243. #endif
  1244.                 }
  1245.             }
  1246. #ifdef ZHLT_TEXLIGHT
  1247.             MakePatchForFace(fn, w, style); //LRC
  1248. #else
  1249.             MakePatchForFace(fn, w);
  1250. #endif
  1251.         }
  1252.     }
  1253.  
  1254.     Log("%i base patches\n", g_num_patches);
  1255.     Log("%i opaque faces\n", g_opaque_face_count);
  1256.     Log("%i square feet [%.2f square inches]\n", (int)(totalarea / 144), totalarea);
  1257. }
  1258.  
  1259. // =====================================================================================
  1260. //  patch_sorter
  1261. // =====================================================================================
  1262. static int CDECL patch_sorter(const void* p1, const void* p2)
  1263. {
  1264.     patch_t*        patch1 = (patch_t*)p1;
  1265.     patch_t*        patch2 = (patch_t*)p2;
  1266.  
  1267.     if (patch1->faceNumber < patch2->faceNumber)
  1268.     {
  1269.         return -1;
  1270.     }
  1271.     else if (patch1->faceNumber > patch2->faceNumber)
  1272.     {
  1273.         return 1;
  1274.     }
  1275.     else
  1276.     {
  1277.         return 0;
  1278.     }
  1279. }
  1280.  
  1281. // =====================================================================================
  1282. //  patch_sorter
  1283. //      This sorts the patches by facenumber, which makes their runs compress even better
  1284. // =====================================================================================
  1285. static void     SortPatches()
  1286. {
  1287.     qsort((void*)g_patches, (size_t) g_num_patches, sizeof(patch_t), patch_sorter);
  1288.  
  1289.     // Fixup g_face_patches & Fixup patch->next
  1290.     memset(g_face_patches, 0, sizeof(g_face_patches));
  1291.     {
  1292.         unsigned        x;
  1293.         patch_t*        patch = g_patches + 1;
  1294.         patch_t*        prev = g_patches;
  1295.  
  1296.         g_face_patches[0] = g_patches;
  1297.  
  1298.         for (x = 1; x < g_num_patches; x++, patch++)
  1299.         {
  1300.             if (patch->faceNumber != prev->faceNumber)
  1301.             {
  1302.                 prev->next = NULL;
  1303.                 g_face_patches[patch->faceNumber] = patch;
  1304.             }
  1305.             else
  1306.             {
  1307.                 prev->next = patch;
  1308.             }
  1309.             prev = patch;
  1310.         }
  1311.     }
  1312. }
  1313.  
  1314. // =====================================================================================
  1315. //  FreePatches
  1316. // =====================================================================================
  1317. static void     FreePatches()
  1318. {
  1319.     unsigned        x;
  1320.     patch_t*        patch = g_patches;
  1321.  
  1322.     // AJM EX
  1323.     //Log("patches: %i of %i (%2.2lf percent)\n", g_num_patches, MAX_PATCHES, (double)((double)g_num_patches / (double)MAX_PATCHES));
  1324.  
  1325.     for (x = 0; x < g_num_patches; x++, patch++)
  1326.     {
  1327.         delete patch->winding;
  1328.     }
  1329.     memset(g_patches, 0, sizeof(patch_t) * g_num_patches);
  1330. }
  1331.  
  1332. //=====================================================================
  1333.  
  1334. // =====================================================================================
  1335. //  WriteWorld
  1336. // =====================================================================================
  1337. static void     WriteWorld(const char* const name)
  1338. {
  1339.     unsigned        i;
  1340.     unsigned        j;
  1341.     FILE*           out;
  1342.     patch_t*        patch;
  1343.     Winding*        w;
  1344.  
  1345.     out = fopen(name, "w");
  1346.  
  1347.     if (!out)
  1348.         Error("Couldn't open %s", name);
  1349.  
  1350.     for (j = 0, patch = g_patches; j < g_num_patches; j++, patch++)
  1351.     {
  1352.         w = patch->winding;
  1353.         Log("%i\n", w->m_NumPoints);
  1354.         for (i = 0; i < w->m_NumPoints; i++)
  1355.         {
  1356. #ifdef ZHLT_TEXLIGHT
  1357.             Log("%5.2f %5.2f %5.2f %5.3f %5.3f %5.3f\n",
  1358.                 w->m_Points[i][0],
  1359.                 w->m_Points[i][1],
  1360.                 w->m_Points[i][2], patch->totallight[0][0] / 256, patch->totallight[0][1] / 256, patch->totallight[0][2] / 256); //LRC
  1361. #else
  1362.             Log("%5.2f %5.2f %5.2f %5.3f %5.3f %5.3f\n",
  1363.                 w->m_Points[i][0],
  1364.                 w->m_Points[i][1],
  1365.                 w->m_Points[i][2], patch->totallight[0] / 256, patch->totallight[1] / 256, patch->totallight[2] / 256);
  1366. #endif
  1367.         }
  1368.         Log("\n");
  1369.     }
  1370.  
  1371.     fclose(out);
  1372. }
  1373.  
  1374. // =====================================================================================
  1375. //  CollectLight
  1376. // =====================================================================================
  1377. static void     CollectLight()
  1378. {
  1379. #ifdef ZHLT_TEXLIGHT
  1380.     unsigned        j; //LRC
  1381. #endif
  1382.     unsigned        i;
  1383.     patch_t*        patch;
  1384.  
  1385.     for (i = 0, patch = g_patches; i < g_num_patches; i++, patch++)
  1386.     {
  1387. #ifdef ZHLT_TEXLIGHT
  1388.          //LRC
  1389.         for (j = 0; j < MAXLIGHTMAPS && patch->totalstyle[j] != 255; j++)
  1390.         {
  1391.             VectorAdd(patch->totallight[j], addlight[i][j], patch->totallight[j]);
  1392.             VectorScale(addlight[i][j], TRANSFER_SCALE, emitlight[i][j]);
  1393.             VectorClear(addlight[i][j]);
  1394.         }
  1395. #else
  1396.         VectorAdd(patch->totallight, addlight[i], patch->totallight);
  1397.         VectorScale(addlight[i], TRANSFER_SCALE, emitlight[i]);
  1398.         VectorClear(addlight[i]);
  1399. #endif
  1400.     }
  1401. }
  1402.  
  1403. // =====================================================================================
  1404. //  GatherLight
  1405. //      Get light from other g_patches
  1406. //      Run multi-threaded
  1407. // =====================================================================================
  1408. #ifdef SYSTEM_WIN32
  1409. #pragma warning(push)
  1410. #pragma warning(disable: 4100)                             // unreferenced formal parameter
  1411. #endif
  1412. static void     GatherLight(int threadnum)
  1413. {
  1414.     int             j;
  1415.     patch_t*        patch;
  1416.  
  1417. #ifdef ZHLT_TEXLIGHT
  1418.     unsigned        k,m; //LRC
  1419. //LRC    vec3_t          sum;
  1420. #else
  1421.     unsigned        k;
  1422.     vec3_t          sum;
  1423. #endif
  1424.  
  1425.     unsigned        iIndex;
  1426.     transfer_data_t* tData;
  1427.     transfer_index_t* tIndex;
  1428.  
  1429.     while (1)
  1430.     {
  1431.         j = GetThreadWork();
  1432.         if (j == -1)
  1433.         {
  1434.             break;
  1435.         }
  1436.  
  1437.         patch = &g_patches[j];
  1438.  
  1439.         tData = patch->tData;
  1440.         tIndex = patch->tIndex;
  1441.         iIndex = patch->iIndex;
  1442.  
  1443. #ifdef ZHLT_TEXLIGHT
  1444.           //LRC
  1445.         for (m = 0; m < MAXLIGHTMAPS && patch->totalstyle[m] != 255; m++)
  1446.         {
  1447.             VectorClear(addlight[j][m]);
  1448.         }
  1449. #else
  1450.         VectorClear(sum);
  1451. #endif
  1452.  
  1453.         for (k = 0; k < iIndex; k++, tIndex++)
  1454.         {
  1455.             unsigned        l;
  1456.             unsigned        size = (tIndex->size + 1);
  1457.             unsigned        patchnum = tIndex->index;
  1458.  
  1459.             for (l = 0; l < size; l++, tData++, patchnum++)
  1460.             {
  1461.                 vec3_t          v;
  1462. #ifdef ZHLT_TEXLIGHT
  1463.                  //LRC:
  1464.                 patch_t*        emitpatch = &g_patches[patchnum];
  1465.                 unsigned        emitstyle;
  1466.  
  1467.                 // for each style on the emitting patch
  1468.                 for (emitstyle = 0; emitstyle < MAXLIGHTMAPS && emitpatch->totalstyle[emitstyle] != 255; emitstyle++)
  1469.                 {
  1470.                     // find the matching style on this (destination) patch
  1471.                     for (m = 0; m < MAXLIGHTMAPS && patch->totalstyle[m] != 255; m++)
  1472.                     {
  1473.                         if (patch->totalstyle[m] == emitpatch->totalstyle[emitstyle])
  1474.                         {
  1475.                             break;
  1476.                         }
  1477.                     }
  1478.  
  1479.                     if (m == MAXLIGHTMAPS)
  1480.                     {
  1481.                         Warning("Too many direct light styles on a face(?,?,?)");
  1482.                     }
  1483.                     else
  1484.                     {
  1485.                         if (patch->totalstyle[m] == 255)
  1486.                         {
  1487.                             patch->totalstyle[m] = emitpatch->totalstyle[emitstyle];
  1488. //                            Log("Granting new style %d to patch at idx %d\n", patch->totalstyle[m], m);
  1489.                         }
  1490.                         VectorScale(emitlight[patchnum][emitstyle], (*tData), v);
  1491.                         if (isPointFinite(v))
  1492.                         {
  1493.                             VectorAdd(addlight[j][m], v, addlight[j][m]);
  1494.                         }
  1495.                         else
  1496.                         {
  1497.                             Verbose("GatherLight, v (%4.3f %4.3f %4.3f)@(%4.3f %4.3f %4.3f)\n",
  1498.                                 v[0], v[1], v[2], patch->origin[0], patch->origin[1], patch->origin[2]);
  1499.                         }
  1500.                     }
  1501.                 }
  1502.                 //LRC (ends)
  1503. #else
  1504.                 VectorScale(emitlight[patchnum], (*tData), v);
  1505.                 if (isPointFinite(v))
  1506.                 {
  1507.                     VectorAdd(sum, v, sum);
  1508.                 }
  1509.                 else
  1510.                 {
  1511.                     Verbose("GatherLight, v (%4.3f %4.3f %4.3f)@(%4.3f %4.3f %4.3f)\n",
  1512.                             v[0], v[1], v[2], patch->origin[0], patch->origin[1], patch->origin[2]);
  1513.                 }
  1514. #endif
  1515.             }
  1516.         }
  1517.  
  1518. #ifdef ZHLT_TEXLIGHT
  1519.         //LRC        VectorCopy(sum, addlight[j]);
  1520. #else
  1521.         VectorCopy(sum, addlight[j]);
  1522. #endif
  1523.     }
  1524. }
  1525.  
  1526. // RGB Transfer version
  1527. #ifdef HLRAD_HULLU
  1528. static void     GatherRGBLight(int threadnum)
  1529. {
  1530.     int             j;
  1531.     patch_t*        patch;
  1532.  
  1533. #ifdef ZHLT_TEXLIGHT
  1534.     unsigned        k,m; //LRC
  1535. //LRC    vec3_t          sum;
  1536. #else
  1537.     unsigned        k;
  1538.     vec3_t          sum;
  1539. #endif
  1540.  
  1541.     unsigned        iIndex;
  1542.     rgb_transfer_data_t* tRGBData;
  1543.     transfer_index_t* tIndex;
  1544.  
  1545.     while (1)
  1546.     {
  1547.         j = GetThreadWork();
  1548.         if (j == -1)
  1549.         {
  1550.             break;
  1551.         }
  1552.  
  1553.         patch = &g_patches[j];
  1554.  
  1555.         tRGBData = patch->tRGBData;
  1556.         tIndex = patch->tIndex;
  1557.         iIndex = patch->iIndex;
  1558.  
  1559. #ifdef ZHLT_TEXLIGHT
  1560.           //LRC
  1561.         for (m = 0; m < MAXLIGHTMAPS && patch->totalstyle[m] != 255; m++)
  1562.         {
  1563.             VectorClear(addlight[j][m]);
  1564.         }
  1565. #else
  1566.         VectorClear(sum);
  1567. #endif
  1568.  
  1569.         for (k = 0; k < iIndex; k++, tIndex++)
  1570.         {
  1571.             unsigned        l;
  1572.             unsigned        size = (tIndex->size + 1);
  1573.             unsigned        patchnum = tIndex->index;
  1574.  
  1575.             for (l = 0; l < size; l++, tRGBData++, patchnum++)
  1576.             {
  1577.                 vec3_t          v;
  1578. #ifdef ZHLT_TEXLIGHT
  1579.                  //LRC:
  1580.                 patch_t*        emitpatch = &g_patches[patchnum];
  1581.                 unsigned        emitstyle;
  1582.  
  1583.                 // for each style on the emitting patch
  1584.                 for (emitstyle = 0; emitstyle < MAXLIGHTMAPS && emitpatch->totalstyle[emitstyle] != 255; emitstyle++)
  1585.                 {
  1586.                     // find the matching style on this (destination) patch
  1587.                     for (m = 0; m < MAXLIGHTMAPS && patch->totalstyle[m] != 255; m++)
  1588.                     {
  1589.                         if (patch->totalstyle[m] == emitpatch->totalstyle[emitstyle])
  1590.                         {
  1591.                             break;
  1592.                         }
  1593.                     }
  1594.  
  1595.                     if (m == MAXLIGHTMAPS)
  1596.                     {
  1597.                         Warning("Too many direct light styles on a face(?,?,?)");
  1598.                     }
  1599.                     else
  1600.                     {
  1601.                         if (patch->totalstyle[m] == 255)
  1602.                         {
  1603.                             patch->totalstyle[m] = emitpatch->totalstyle[emitstyle];
  1604. //                            Log("Granting new style %d to patch at idx %d\n", patch->totalstyle[m], m);
  1605.                         }
  1606.                         VectorMultiply(emitlight[patchnum][emitstyle], (*tRGBData), v);
  1607.                         if (isPointFinite(v))
  1608.                         {
  1609.                             VectorAdd(addlight[j][m], v, addlight[j][m]);
  1610.                         }
  1611.                         else
  1612.                         {
  1613.                             Verbose("GatherLight, v (%4.3f %4.3f %4.3f)@(%4.3f %4.3f %4.3f)\n",
  1614.                                 v[0], v[1], v[2], patch->origin[0], patch->origin[1], patch->origin[2]);
  1615.                         }
  1616.                     }
  1617.                 }
  1618.                 //LRC (ends)
  1619. #else
  1620.                 VectorMultiply(emitlight[patchnum], (*tRGBData), v);
  1621.                 if (isPointFinite(v))
  1622.                 {
  1623.                     VectorAdd(sum, v, sum);
  1624.                 }
  1625.                 else
  1626.                 {
  1627.                     Verbose("GatherLight, v (%4.3f %4.3f %4.3f)@(%4.3f %4.3f %4.3f)\n",
  1628.                             v[0], v[1], v[2], patch->origin[0], patch->origin[1], patch->origin[2]);
  1629.                 }
  1630. #endif
  1631.             }
  1632.         }
  1633.  
  1634. #ifdef ZHLT_TEXLIGHT
  1635.         //LRC        VectorCopy(sum, addlight[j]);
  1636. #else
  1637.         VectorCopy(sum, addlight[j]);
  1638. #endif
  1639.     }
  1640. }
  1641. #endif
  1642.  
  1643. #ifdef SYSTEM_WIN32
  1644. #pragma warning(pop)
  1645. #endif
  1646.  
  1647. // =====================================================================================
  1648. //  BounceLight
  1649. // =====================================================================================
  1650. static void     BounceLight()
  1651. {
  1652.     unsigned        i;
  1653.     char            name[64];
  1654.  
  1655. #ifdef ZHLT_TEXLIGHT
  1656.     unsigned        j; //LRC
  1657. #endif
  1658.  
  1659.     for (i = 0; i < g_num_patches; i++)
  1660.     {
  1661. #ifdef ZHLT_TEXLIGHT
  1662.         //LRC
  1663.         for (j = 0; j < MAXLIGHTMAPS && g_patches[i].totalstyle[j] != 255; j++)
  1664.         {
  1665.             VectorScale(g_patches[i].totallight[j], TRANSFER_SCALE, emitlight[i][j]);
  1666.         }
  1667. #else
  1668.         VectorScale(g_patches[i].totallight, TRANSFER_SCALE, emitlight[i]);
  1669. #endif
  1670.     }
  1671.  
  1672.     for (i = 0; i < g_numbounce; i++)
  1673.     {
  1674.         printf("Bounce %u ", i + 1);
  1675. #ifdef HLRAD_HULLU
  1676.     if(g_rgb_transfers)
  1677.                {NamedRunThreadsOn(g_num_patches, g_estimate, GatherRGBLight);}
  1678.         else
  1679.             {NamedRunThreadsOn(g_num_patches, g_estimate, GatherLight);}
  1680. #else
  1681.     NamedRunThreadsOn(g_num_patches, g_estimate, GatherLight);
  1682. #endif
  1683.         CollectLight();
  1684.  
  1685.         if (g_dumppatches)
  1686.         {
  1687.             sprintf(name, "bounce%u.txt", i);
  1688.             WriteWorld(name);
  1689.         }
  1690.     }
  1691. }
  1692.  
  1693. // =====================================================================================
  1694. //  CheckMaxPatches
  1695. // =====================================================================================
  1696. static void     CheckMaxPatches()
  1697. {
  1698.     switch (g_method)
  1699.     {
  1700.     case eMethodVismatrix:
  1701.         hlassume(g_num_patches < MAX_VISMATRIX_PATCHES, assume_MAX_PATCHES);
  1702.         break;
  1703.     case eMethodSparseVismatrix:
  1704.         hlassume(g_num_patches < MAX_SPARSE_VISMATRIX_PATCHES, assume_MAX_PATCHES);
  1705.         break;
  1706.     case eMethodNoVismatrix:
  1707.         hlassume(g_num_patches < MAX_PATCHES, assume_MAX_PATCHES);
  1708.         break;
  1709.     }
  1710. }
  1711.  
  1712. // =====================================================================================
  1713. //  MakeScalesStub
  1714. // =====================================================================================
  1715. static void     MakeScalesStub()
  1716. {
  1717.     switch (g_method)
  1718.     {
  1719.     case eMethodVismatrix:
  1720.         MakeScalesVismatrix();
  1721.         break;
  1722.     case eMethodSparseVismatrix:
  1723.         MakeScalesSparseVismatrix();
  1724.         break;
  1725.     case eMethodNoVismatrix:
  1726.         MakeScalesNoVismatrix();
  1727.         break;
  1728.     }
  1729. }
  1730.  
  1731. // =====================================================================================
  1732. //  FreeTransfers
  1733. // =====================================================================================
  1734. static void     FreeTransfers()
  1735. {
  1736.     unsigned        x;
  1737.     patch_t*        patch = g_patches;
  1738.  
  1739.     for (x = 0; x < g_num_patches; x++, patch++)
  1740.     {
  1741.         if (patch->tData)
  1742.         {
  1743.             FreeBlock(patch->tData);
  1744.             patch->tData = NULL;
  1745.         }
  1746. #ifdef HLRAD_HULLU
  1747.         if (patch->tRGBData)
  1748.         {
  1749.             FreeBlock(patch->tRGBData);
  1750.             patch->tRGBData = NULL;
  1751.         }
  1752. #endif
  1753.         if (patch->tIndex)
  1754.         {
  1755.             FreeBlock(patch->tIndex);
  1756.             patch->tIndex = NULL;
  1757.         }
  1758.     }
  1759. }
  1760.  
  1761. // =====================================================================================
  1762. //  RadWorld
  1763. // =====================================================================================
  1764. static void     RadWorld()
  1765. {
  1766.     unsigned        i;
  1767. #ifdef ZHLT_TEXLIGHT
  1768.     unsigned        j;
  1769. #endif
  1770.  
  1771.     MakeBackplanes();
  1772.     MakeParents(0, -1);
  1773.     MakeTnodes(&g_dmodels[0]);
  1774.  
  1775.     // turn each face into a single patch
  1776.     MakePatches();
  1777.     CheckMaxPatches();                                     // Check here for exceeding max patches, to prevent a lot of work from occuring before an error occurs
  1778.     SortPatches();                                         // Makes the runs in the Transfer Compression really good
  1779.     PairEdges();
  1780.  
  1781.     // create directlights out of g_patches and lights
  1782.     CreateDirectLights();
  1783.  
  1784.     Log("\n");
  1785.  
  1786.     // build initial facelights
  1787.     NamedRunThreadsOnIndividual(g_numfaces, g_estimate, BuildFacelights);
  1788.  
  1789.     // free up the direct lights now that we have facelights
  1790.     DeleteDirectLights();
  1791.  
  1792.     if (g_numbounce > 0)
  1793.     {
  1794.         // build transfer lists
  1795.         MakeScalesStub();
  1796.  
  1797.         // spread light around
  1798.         BounceLight();
  1799.  
  1800.         for (i = 0; i < g_num_patches; i++)
  1801.         {
  1802. #ifdef ZHLT_TEXLIGHT// AJM
  1803.             for (j = 0; j < MAXLIGHTMAPS && g_patches[i].totalstyle[j] != 255; j++)
  1804.             {
  1805.                 VectorSubtract(g_patches[i].totallight[j], g_patches[i].directlight[j], g_patches[i].totallight[j]);
  1806.             }
  1807. #else
  1808.             VectorSubtract(g_patches[i].totallight, g_patches[i].directlight, g_patches[i].totallight);
  1809. #endif
  1810.         }
  1811.     }
  1812.  
  1813.     FreeTransfers();
  1814.  
  1815.     // blend bounced light into direct light and save
  1816.     PrecompLightmapOffsets();
  1817.  
  1818.     NamedRunThreadsOnIndividual(g_numfaces, g_estimate, FinalLightFace);
  1819. }
  1820.  
  1821. // =====================================================================================
  1822. //  Usage
  1823. // =====================================================================================
  1824. static void     Usage()
  1825. {
  1826.     Banner();
  1827.  
  1828.     Log("\n-= %s Options =-\n\n", g_Program);
  1829.     Log("    -sparse         : Enable low memory vismatrix algorithm\n");
  1830.     Log("    -nomatrix       : Disable usage of vismatrix entirely\n\n");
  1831.     Log("    -extra          : Improve lighting quality by doing 9 point oversampling\n");
  1832.     Log("    -bounce #       : Set number of radiosity bounces\n");
  1833.     Log("    -ambient r g b  : Set ambient world light (0.0 to 1.0, r g b)\n");
  1834.     Log("    -maxlight #     : Set maximum light intensity value\n");
  1835.     Log("    -circus         : Enable 'circus' mode for locating unlit lightmaps\n");
  1836.     Log("    -nopaque        : Disable the opaque zhlt_lightflags for this compile\n\n");
  1837.     Log("    -smooth #       : Set smoothing threshold for blending (in degrees)\n");
  1838.     Log("    -chop #         : Set radiosity patch size for normal textures\n");
  1839.     Log("    -texchop #      : Set radiosity patch size for texture light faces\n\n");
  1840.     Log("    -notexscale #   : Do not scale radiosity patches with texture scale\n");
  1841.     Log("    -coring #       : Set lighting threshold before blackness\n");
  1842.     Log("    -dlight #       : Set direct lighting threshold\n");
  1843.     Log("    -nolerp         : Disable radiosity interpolation, nearest point instead\n\n");
  1844.     Log("    -fade #         : Set global fade (larger values = shorter lights)\n");
  1845.     Log("    -falloff #      : Set global falloff mode (1 = inv linear, 2 = inv square)\n");
  1846.     Log("    -scale #        : Set global light scaling value\n");
  1847.     Log("    -gamma #        : Set global gamma value\n\n");
  1848.     Log("    -sky #          : Set ambient sunlight contribution in the shade outside\n");
  1849.     Log("    -lights file    : Manually specify a lights.rad file to use\n");
  1850.     Log("    -noskyfix       : Disable light_environment being global\n");
  1851.     Log("    -incremental    : Use or create an incremental transfer list file\n\n");
  1852.     Log("    -dump           : Dumps light patches to a file for hlrad debugging info\n\n");
  1853.     Log("    -texdata #      : Alter maximum texture memory limit (in kb)\n");
  1854.     Log("    -chart          : display bsp statitics\n");
  1855.     Log("    -low | -high    : run program an altered priority level\n");
  1856.     Log("    -nolog          : Do not generate the compile logfiles\n");
  1857.     Log("    -threads #      : manually specify the number of threads to run\n");
  1858. #ifdef SYSTEM_WIN32
  1859.     Log("    -estimate       : display estimated time during compile\n");
  1860. #endif
  1861. #ifdef ZHLT_PROGRESSFILE // AJM
  1862.     Log("    -progressfile path  : specify the path to a file for progress estimate output\n");
  1863. #endif
  1864. #ifdef SYSTEM_POSIX
  1865.     Log("    -noestimate     : Do not display continuous compile time estimates\n");
  1866. #endif
  1867.     Log("    -verbose        : compile with verbose messages\n");
  1868.     Log("    -noinfo         : Do not show tool configuration information\n");
  1869.     Log("    -dev #          : compile with developer message\n\n");
  1870.  
  1871.     // ------------------------------------------------------------------------
  1872.     // Changes by Adam Foster - afoster@compsoc.man.ac.uk
  1873. #ifdef HLRAD_WHOME
  1874.  
  1875.     // AJM: we dont need this extra crap
  1876.     //Log("-= Unofficial features added by Adam Foster (afoster@compsoc.man.ac.uk) =-\n\n");
  1877.     Log("   -colourgamma r g b  : Sets different gamma values for r, g, b\n" );
  1878.     Log("   -colourscale r g b  : Sets different lightscale values for r, g ,b\n" );
  1879.     Log("   -colourjitter r g b : Adds noise, independent colours, for dithering\n");
  1880.     Log("   -jitter r g b       : Adds noise, monochromatic, for dithering\n");
  1881.     Log("   -nodiffuse          : Disables light_environment diffuse hack\n");
  1882.     Log("   -nospotpoints       : Disables light_spot spherical point sources\n");
  1883.     Log("   -softlight r g b d  : Scaling values for backwards-light hack\n\n");
  1884.     //Log("-= End of unofficial features! =-\n\n" );
  1885.  
  1886. #endif
  1887.     // ------------------------------------------------------------------------  
  1888.     
  1889. #ifdef HLRAD_HULLU
  1890.     Log("   -customshadowwithbounce : Enables custom shadows with bounce light\n");
  1891.     Log("   -rgbtransfers           : Enables RGB Transfers (for custom shadows)\n\n");
  1892. #endif
  1893.  
  1894.     Log("    mapfile         : The mapfile to compile\n\n");
  1895.  
  1896.     exit(1);
  1897. }
  1898.  
  1899. // =====================================================================================
  1900. //  Settings
  1901. // =====================================================================================
  1902. static void     Settings()
  1903. {
  1904.     char*           tmp;
  1905.     char            buf1[1024];
  1906.     char            buf2[1024];
  1907.  
  1908.     if (!g_info)
  1909.     {
  1910.         return;
  1911.     }
  1912.  
  1913.     Log("\n-= Current %s Settings =-\n", g_Program);
  1914.     Log("Name                | Setting             | Default\n"
  1915.         "--------------------|---------------------|-------------------------\n");
  1916.  
  1917.     // ZHLT Common Settings
  1918.     if (DEFAULT_NUMTHREADS == -1)
  1919.     {
  1920.         Log("threads              [ %17d ] [            Varies ]\n", g_numthreads);
  1921.     }
  1922.     else
  1923.     {
  1924.         Log("threads              [ %17d ] [ %17d ]\n", g_numthreads, DEFAULT_NUMTHREADS);
  1925.     }
  1926.  
  1927.     Log("verbose              [ %17s ] [ %17s ]\n", g_verbose ? "on" : "off", DEFAULT_VERBOSE ? "on" : "off");
  1928.     Log("log                  [ %17s ] [ %17s ]\n", g_log ? "on" : "off", DEFAULT_LOG ? "on" : "off");
  1929.     Log("developer            [ %17d ] [ %17d ]\n", g_developer, DEFAULT_DEVELOPER);
  1930.     Log("chart                [ %17s ] [ %17s ]\n", g_chart ? "on" : "off", DEFAULT_CHART ? "on" : "off");
  1931.     Log("estimate             [ %17s ] [ %17s ]\n", g_estimate ? "on" : "off", DEFAULT_ESTIMATE ? "on" : "off");
  1932.     Log("max texture memory   [ %17d ] [ %17d ]\n", g_max_map_miptex, DEFAULT_MAX_MAP_MIPTEX);
  1933.  
  1934.     switch (g_threadpriority)
  1935.     {
  1936.     case eThreadPriorityNormal:
  1937.     default:
  1938.         tmp = "Normal";
  1939.         break;
  1940.     case eThreadPriorityLow:
  1941.         tmp = "Low";
  1942.         break;
  1943.     case eThreadPriorityHigh:
  1944.         tmp = "High";
  1945.         break;
  1946.     }
  1947.     Log("priority             [ %17s ] [ %17s ]\n", tmp, "Normal");
  1948.     Log("\n");
  1949.  
  1950.     // HLRAD Specific Settings
  1951.     switch (g_method)
  1952.     {
  1953.     default:
  1954.         tmp = "Unknown";
  1955.         break;
  1956.     case eMethodVismatrix:
  1957.         tmp = "Original";
  1958.         break;
  1959.     case eMethodSparseVismatrix:
  1960.         tmp = "Sparse";
  1961.         break;
  1962.     case eMethodNoVismatrix:
  1963.         tmp = "NoMatrix";
  1964.         break;
  1965.     }
  1966.  
  1967.     Log("vismatrix algorithm  [ %17s ] [ %17s ]\n", tmp, "Original");
  1968.     Log("oversampling (-extra)[ %17s ] [ %17s ]\n", g_extra ? "on" : "off", DEFAULT_EXTRA ? "on" : "off");
  1969.     Log("bounces              [ %17d ] [ %17d ]\n", g_numbounce, DEFAULT_BOUNCE);
  1970.  
  1971.     safe_snprintf(buf1, sizeof(buf1), "%1.3f %1.3f %1.3f", g_ambient[0], g_ambient[1], g_ambient[2]);
  1972.     safe_snprintf(buf2, sizeof(buf2), "%1.3f %1.3f %1.3f", DEFAULT_AMBIENT_RED, DEFAULT_AMBIENT_GREEN, DEFAULT_AMBIENT_BLUE);
  1973.     Log("ambient light        [ %17s ] [ %17s ]\n", buf1, buf2);
  1974.     safe_snprintf(buf1, sizeof(buf1), "%3.3f", g_maxlight);
  1975.     safe_snprintf(buf2, sizeof(buf2), "%3.3f", DEFAULT_MAXLIGHT);
  1976.     Log("maximum light        [ %17s ] [ %17s ]\n", buf1, buf2);
  1977.     Log("circus mode          [ %17s ] [ %17s ]\n", g_circus ? "on" : "off", DEFAULT_CIRCUS ? "on" : "off");
  1978.  
  1979.     Log("\n");
  1980.  
  1981.     safe_snprintf(buf1, sizeof(buf1), "%3.3f", g_smoothing_value);
  1982.     safe_snprintf(buf2, sizeof(buf2), "%3.3f", DEFAULT_SMOOTHING_VALUE);
  1983.     Log("smoothing threshold  [ %17s ] [ %17s ]\n", buf1, buf2);
  1984.     safe_snprintf(buf1, sizeof(buf1), "%3.3f", g_dlight_threshold);
  1985.     safe_snprintf(buf2, sizeof(buf2), "%3.3f", DEFAULT_DLIGHT_THRESHOLD);
  1986.     Log("direct threshold     [ %17s ] [ %17s ]\n", buf1, buf2);
  1987.     safe_snprintf(buf1, sizeof(buf1), "%3.3f", g_direct_scale);
  1988.     safe_snprintf(buf2, sizeof(buf2), "%3.3f", DEFAULT_DLIGHT_SCALE);
  1989.     Log("direct light scale   [ %17s ] [ %17s ]\n", buf1, buf2);
  1990.     safe_snprintf(buf1, sizeof(buf1), "%3.3f", g_coring);
  1991.     safe_snprintf(buf2, sizeof(buf2), "%3.3f", DEFAULT_CORING);
  1992.     Log("coring threshold     [ %17s ] [ %17s ]\n", buf1, buf2);
  1993.     Log("patch interpolation  [ %17s ] [ %17s ]\n", g_lerp_enabled ? "on" : "off", DEFAULT_LERP_ENABLED ? "on" : "off");
  1994.  
  1995.     Log("\n");
  1996.  
  1997.     Log("texscale             [ %17s ] [ %17s ]\n", g_texscale ? "on" : "off", DEFAULT_TEXSCALE ? "on" : "off");
  1998.     Log("patch subdividing    [ %17s ] [ %17s ]\n", g_subdivide ? "on" : "off", DEFAULT_SUBDIVIDE ? "on" : "off");
  1999.     safe_snprintf(buf1, sizeof(buf1), "%3.3f", g_chop);
  2000.     safe_snprintf(buf2, sizeof(buf2), "%3.3f", DEFAULT_CHOP);
  2001.     Log("chop value           [ %17s ] [ %17s ]\n", buf1, buf2);
  2002.     safe_snprintf(buf1, sizeof(buf1), "%3.3f", g_texchop);
  2003.     safe_snprintf(buf2, sizeof(buf2), "%3.3f", DEFAULT_TEXCHOP);
  2004.     Log("texchop value        [ %17s ] [ %17s ]\n", buf1, buf2);
  2005.     Log("\n");
  2006.  
  2007.     safe_snprintf(buf1, sizeof(buf1), "%3.3f", g_fade);
  2008.     safe_snprintf(buf2, sizeof(buf2), "%3.3f", DEFAULT_FADE);
  2009.     Log("global fade          [ %17s ] [ %17s ]\n", buf1, buf2);
  2010.     Log("global falloff       [ %17d ] [ %17d ]\n", g_falloff, DEFAULT_FALLOFF);
  2011.     
  2012.     // ------------------------------------------------------------------------
  2013.     // Changes by Adam Foster - afoster@compsoc.man.ac.uk
  2014.     // replaces the old stuff for displaying current values for gamma and lightscale
  2015. #ifdef HLRAD_WHOME
  2016.     safe_snprintf(buf1, sizeof(buf1), "%1.3f %1.3f %1.3f", g_colour_lightscale[0], g_colour_lightscale[1], g_colour_lightscale[2]);
  2017.     safe_snprintf(buf2, sizeof(buf2), "%1.3f %1.3f %1.3f", DEFAULT_COLOUR_LIGHTSCALE_RED, DEFAULT_COLOUR_LIGHTSCALE_GREEN, DEFAULT_COLOUR_LIGHTSCALE_BLUE);
  2018.     Log("global light scale   [ %17s ] [ %17s ]\n", buf1, buf2);
  2019.  
  2020.     safe_snprintf(buf1, sizeof(buf1), "%1.3f %1.3f %1.3f", g_colour_qgamma[0], g_colour_qgamma[1], g_colour_qgamma[2]);
  2021.     safe_snprintf(buf2, sizeof(buf2), "%1.3f %1.3f %1.3f", DEFAULT_COLOUR_GAMMA_RED, DEFAULT_COLOUR_GAMMA_GREEN, DEFAULT_COLOUR_GAMMA_BLUE);
  2022.     Log("global gamma         [ %17s ] [ %17s ]\n", buf1, buf2);
  2023. #endif
  2024.     // ------------------------------------------------------------------------
  2025.  
  2026.     safe_snprintf(buf1, sizeof(buf1), "%3.3f", g_lightscale);
  2027.     safe_snprintf(buf2, sizeof(buf2), "%3.3f", DEFAULT_LIGHTSCALE);
  2028.     Log("global light scale   [ %17s ] [ %17s ]\n", buf1, buf2);
  2029.  
  2030. #ifndef HLRAD_WHOME
  2031.     safe_snprintf(buf1, sizeof(buf1), "%3.3f", g_qgamma);
  2032.     safe_snprintf(buf2, sizeof(buf2), "%3.3f", DEFAULT_GAMMA);
  2033.     Log("global gamma amount  [ %17s ] [ %17s ]\n", buf1, buf2);
  2034. #endif
  2035.  
  2036.     safe_snprintf(buf1, sizeof(buf1), "%3.3f", g_indirect_sun);
  2037.     safe_snprintf(buf2, sizeof(buf2), "%3.3f", DEFAULT_INDIRECT_SUN);
  2038.     Log("global sky diffusion [ %17s ] [ %17s ]\n", buf1, buf2);
  2039.  
  2040.     Log("\n");
  2041.     Log("opaque entities      [ %17s ] [ %17s ]\n", g_allow_opaques ? "on" : "off", DEFAULT_ALLOW_OPAQUES ? "on" : "off");
  2042.     Log("sky lighting fix     [ %17s ] [ %17s ]\n", g_sky_lighting_fix ? "on" : "off", DEFAULT_SKY_LIGHTING_FIX ? "on" : "off");
  2043.     Log("incremental          [ %17s ] [ %17s ]\n", g_incremental ? "on" : "off", DEFAULT_INCREMENTAL ? "on" : "off");
  2044.     Log("dump                 [ %17s ] [ %17s ]\n", g_dumppatches ? "on" : "off", DEFAULT_DUMPPATCHES ? "on" : "off");
  2045.  
  2046.     // ------------------------------------------------------------------------
  2047.     // Changes by Adam Foster - afoster@compsoc.man.ac.uk
  2048.     // displays information on all the brand-new features :)
  2049. #ifdef HLRAD_WHOME
  2050.  
  2051.     Log("\n");
  2052.     safe_snprintf(buf1, sizeof(buf1), "%3.1f %3.1f %3.1f", g_colour_jitter_hack[0], g_colour_jitter_hack[1], g_colour_jitter_hack[2]);
  2053.     safe_snprintf(buf2, sizeof(buf2), "%3.1f %3.1f %3.1f", DEFAULT_COLOUR_JITTER_HACK_RED, DEFAULT_COLOUR_JITTER_HACK_GREEN, DEFAULT_COLOUR_JITTER_HACK_BLUE);
  2054.     Log("colour jitter        [ %17s ] [ %17s ]\n", buf1, buf2);
  2055.     safe_snprintf(buf1, sizeof(buf1), "%3.1f %3.1f %3.1f", g_jitter_hack[0], g_jitter_hack[1], g_jitter_hack[2]);
  2056.     safe_snprintf(buf2, sizeof(buf2), "%3.1f %3.1f %3.1f", DEFAULT_JITTER_HACK_RED, DEFAULT_JITTER_HACK_GREEN, DEFAULT_JITTER_HACK_BLUE);
  2057.     Log("monochromatic jitter [ %17s ] [ %17s ]\n", buf1, buf2);
  2058.  
  2059.     safe_snprintf(buf1, sizeof(buf1), "%2.1f %2.1f %2.1f %2.1f", g_softlight_hack[0], g_softlight_hack[1], g_softlight_hack[2], g_softlight_hack_distance);
  2060.     safe_snprintf(buf2, sizeof(buf2), "%2.1f %2.1f %2.1f %2.1f", DEFAULT_SOFTLIGHT_HACK_RED, DEFAULT_SOFTLIGHT_HACK_GREEN, DEFAULT_SOFTLIGHT_HACK_BLUE, DEFAULT_SOFTLIGHT_HACK_DISTANCE);
  2061.     Log("softlight hack       [ %17s ] [ %17s ]\n", buf1, buf2);
  2062.  
  2063.     Log("diffuse hack         [ %17s ] [ %17s ]\n", g_diffuse_hack ? "on" : "off", DEFAULT_DIFFUSE_HACK ? "on" : "off");
  2064.     Log("spotlight points     [ %17s ] [ %17s ]\n", g_spotlight_hack ? "on" : "off", DEFAULT_SPOTLIGHT_HACK ? "on" : "off");
  2065.  
  2066. #endif
  2067.     // ------------------------------------------------------------------------
  2068.  
  2069. #ifdef HLRAD_HULLU
  2070.     Log("\n");
  2071.     Log("custom shadows with bounce light\n"
  2072.         "                     [ %17s ] [ %17s ]\n", g_customshadow_with_bouncelight ? "on" : "off", DEFAULT_CUSTOMSHADOW_WITH_BOUNCELIGHT ? "on" : "off");
  2073.     Log("rgb transfers        [ %17s ] [ %17s ]\n", g_rgb_transfers ? "on" : "off", DEFAULT_RGB_TRANSFERS ? "on" : "off"); 
  2074. #endif
  2075.  
  2076.     Log("\n\n");
  2077. }
  2078.  
  2079. #ifdef HLRAD_INFO_TEXLIGHTS
  2080. // AJM: added in
  2081. // =====================================================================================
  2082. //  ReadInfoTexlights
  2083. //      try and parse texlight info from the info_texlights entity 
  2084. // =====================================================================================
  2085. void            ReadInfoTexlights()
  2086. {
  2087.     int         k;
  2088.     int         values;
  2089.     int         numtexlights = 0;
  2090.     float       r, g, b, i;
  2091.     entity_t*   mapent;
  2092.     epair_t*    ep;
  2093.     texlight_t  texlight;
  2094.  
  2095.     for (k = 0; k < g_numentities; k++)
  2096.     {
  2097.         mapent = &g_entities[k];
  2098.         
  2099.         if (strcmp(ValueForKey(mapent, "classname"), "info_texlights"))
  2100.             continue;
  2101.  
  2102.         Log("[Reading texlights from info_texlights map entity]\n");
  2103.  
  2104.         for (ep = mapent->epairs; ep; ep = ep->next)
  2105.         {
  2106.             if (    !strcmp(ep->key, "classname") 
  2107.                  || !strcmp(ep->key, "origin")
  2108.                )
  2109.                 continue; // we dont care about these keyvalues
  2110.  
  2111.             values = sscanf(ep->value, "%f %f %f %f", &r, &g, &b, &i);
  2112.             
  2113.             if (values == 1)
  2114.             {  
  2115.                 g = b = r;
  2116.             }
  2117.             else if (values == 4) // use brightness value.
  2118.             {
  2119.                 r *= i / 255.0;
  2120.                 g *= i / 255.0;
  2121.                 b *= i / 255.0;
  2122.             }
  2123.             else if (values != 3)
  2124.             {
  2125.                 Warning("ignoring bad texlight '%s' in info_texlights entity", ep->key);
  2126.                 continue;
  2127.             }
  2128.  
  2129.             texlight.name = ep->key;
  2130.             texlight.value[0] = r;
  2131.             texlight.value[1] = g;
  2132.             texlight.value[2] = b;
  2133.             texlight.filename = "info_texlights";
  2134.             s_texlights.push_back(texlight);
  2135.             numtexlights++;
  2136.         }
  2137.  
  2138.         Log("[%i texlights parsed from info_texlights map entity]\n\n", numtexlights);
  2139.     }
  2140. }
  2141. #endif
  2142.  
  2143. const char* lights_rad = "lights.rad";
  2144. const char* ext_rad = ".rad";
  2145. // =====================================================================================
  2146. //  LoadRadFiles
  2147. // =====================================================================================
  2148. void            LoadRadFiles(const char* const mapname, const char* const user_rad, const char* argv0)
  2149. {
  2150.     char global_lights[_MAX_PATH];
  2151.     char mapname_lights[_MAX_PATH];
  2152.  
  2153.     char mapfile[_MAX_PATH];
  2154.     char mapdir[_MAX_PATH];
  2155.     char appdir[_MAX_PATH];
  2156.  
  2157.     // Get application directory (only an approximation on posix systems)
  2158.     // try looking in the directory we were run from
  2159.     {
  2160.         char tmp[_MAX_PATH];
  2161.         memset(tmp, 0, sizeof(tmp));
  2162. #ifdef SYSTEM_WIN32
  2163.         GetModuleFileName(NULL, tmp, _MAX_PATH);
  2164. #else
  2165.         safe_strncpy(tmp, argv0, _MAX_PATH);
  2166. #endif
  2167.         ExtractFilePath(tmp, appdir);
  2168.     }
  2169.  
  2170.     // Get map directory
  2171.     ExtractFilePath(mapname, mapdir);
  2172.     ExtractFileBase(mapname, mapfile);
  2173.  
  2174.     // Look for lights.rad in mapdir
  2175.     safe_strncpy(global_lights, mapdir, _MAX_PATH);
  2176.     safe_strncat(global_lights, lights_rad, _MAX_PATH);
  2177.     if (q_exists(global_lights))
  2178.     {
  2179.         ReadLightFile(global_lights);
  2180.     }
  2181.     else
  2182.     {
  2183.         // Look for lights.rad in appdir
  2184.         safe_strncpy(global_lights, appdir, _MAX_PATH);
  2185.         safe_strncat(global_lights, lights_rad, _MAX_PATH);
  2186.         if (q_exists(global_lights))
  2187.         {
  2188.             ReadLightFile(global_lights);
  2189.         }
  2190.         else
  2191.         {
  2192.             // Look for lights.rad in current working directory
  2193.             safe_strncpy(global_lights, lights_rad, _MAX_PATH);
  2194.             if (q_exists(global_lights))
  2195.             {
  2196.                 ReadLightFile(global_lights);
  2197.             }
  2198.         }
  2199.     }
  2200.    
  2201.     // Look for mapname.rad in mapdir
  2202.     safe_strncpy(mapname_lights, mapdir, _MAX_PATH);
  2203.     safe_strncat(mapname_lights, mapfile, _MAX_PATH);
  2204.     DefaultExtension(mapname_lights, ext_rad);
  2205.     if (q_exists(mapname_lights))
  2206.     {
  2207.         ReadLightFile(mapname_lights);
  2208.     }
  2209.  
  2210.  
  2211.     if (user_rad)
  2212.     {
  2213.         char user_lights[_MAX_PATH];
  2214.         char userfile[_MAX_PATH];
  2215.  
  2216.         ExtractFile(user_rad, userfile);
  2217.  
  2218.         // Look for user.rad from command line (raw)
  2219.         safe_strncpy(user_lights, user_rad, _MAX_PATH);
  2220.         if (q_exists(user_lights))
  2221.         {
  2222.             ReadLightFile(user_lights);
  2223.         }
  2224.         else
  2225.         {
  2226.             // Try again with .rad enforced as extension
  2227.             DefaultExtension(user_lights, ext_rad);
  2228.             if (q_exists(user_lights))
  2229.             {
  2230.                 ReadLightFile(user_lights);
  2231.             }
  2232.             else
  2233.             {
  2234.                 // Look for user.rad in mapdir
  2235.                 safe_strncpy(user_lights, mapdir, _MAX_PATH);
  2236.                 safe_strncat(user_lights, userfile, _MAX_PATH);
  2237.                 DefaultExtension(user_lights, ext_rad);
  2238.                 if (q_exists(user_lights))
  2239.                 {
  2240.                     ReadLightFile(user_lights);
  2241.                 }
  2242.                 else
  2243.                 {
  2244.                     // Look for user.rad in appdir
  2245.                     safe_strncpy(user_lights, appdir, _MAX_PATH);
  2246.                     safe_strncat(user_lights, userfile, _MAX_PATH);
  2247.                     DefaultExtension(user_lights, ext_rad);
  2248.                     if (q_exists(user_lights))
  2249.                     {
  2250.                         ReadLightFile(user_lights);
  2251.                     }
  2252.                     else
  2253.                     {
  2254.                         // Look for user.rad in current working directory
  2255.                         safe_strncpy(user_lights, userfile, _MAX_PATH);
  2256.                         DefaultExtension(user_lights, ext_rad);
  2257.                         if (q_exists(user_lights))
  2258.                         {
  2259.                             ReadLightFile(user_lights);
  2260.                         }
  2261.                     }
  2262.                 }
  2263.             }
  2264.         }
  2265.     }
  2266.  
  2267. #ifdef HLRAD_INFO_TEXLIGHTS
  2268.     ReadInfoTexlights(); // AJM
  2269. #endif
  2270. }
  2271.  
  2272. // =====================================================================================
  2273. //  main
  2274. // =====================================================================================
  2275. int             main(const int argc, char** argv)
  2276. {
  2277.     int             i;
  2278.     double          start, end;
  2279.     const char*     mapname_from_arg = NULL;
  2280.     const char*     user_lights = NULL;
  2281.  
  2282.     g_Program = "hlrad";
  2283.  
  2284.     if (argc == 1)
  2285.         Usage();
  2286.  
  2287.     for (i = 1; i < argc; i++)
  2288.     {
  2289.         if (!strcasecmp(argv[i], "-dump"))
  2290.         {
  2291.             g_dumppatches = true;
  2292.         }
  2293.         else if (!strcasecmp(argv[i], "-bounce"))
  2294.         {
  2295.             if (i < argc)
  2296.             {
  2297.                 g_numbounce = atoi(argv[++i]);
  2298.                 if (g_numbounce > 1000)
  2299.                 {
  2300.                     Log("Unexpectedly large value (>1000) for '-bounce'\n");
  2301.                     Usage();
  2302.                 }
  2303.             }
  2304.             else
  2305.             {
  2306.                 Usage();
  2307.             }
  2308.         }
  2309.         else if (!strcasecmp(argv[i], "-dev"))
  2310.         {
  2311.             if (i < argc)
  2312.             {
  2313.                 g_developer = (developer_level_t)atoi(argv[++i]);
  2314.             }
  2315.             else
  2316.             {
  2317.                 Usage();
  2318.             }
  2319.         }
  2320.         else if (!strcasecmp(argv[i], "-verbose"))
  2321.         {
  2322.             g_verbose = true;
  2323.         }
  2324.         else if (!strcasecmp(argv[i], "-noinfo"))
  2325.         {
  2326.             g_info = false;
  2327.         }
  2328.         else if (!strcasecmp(argv[i], "-threads"))
  2329.         {
  2330.             if (i < argc)
  2331.             {
  2332.                 g_numthreads = atoi(argv[++i]);
  2333.                 if (g_numthreads < 1)
  2334.                 {
  2335.                     Log("Expected value of at least 1 for '-threads'\n");
  2336.                     Usage();
  2337.                 }
  2338.             }
  2339.             else
  2340.             {
  2341.                 Usage();
  2342.             }
  2343.         }
  2344. #ifdef SYSTEM_WIN32
  2345.         else if (!strcasecmp(argv[i], "-estimate"))
  2346.         {
  2347.             g_estimate = true;
  2348.         }
  2349. #endif
  2350. #ifdef SYSTEM_POSIX
  2351.         else if (!strcasecmp(argv[i], "-noestimate"))
  2352.         {
  2353.             g_estimate = false;
  2354.         }
  2355. #endif
  2356. #ifdef ZHLT_NETVIS
  2357.         else if (!strcasecmp(argv[i], "-client"))
  2358.         {
  2359.             if (i < argc)
  2360.             {
  2361.                 g_clientid = atoi(argv[++i]);
  2362.             }
  2363.             else
  2364.             {
  2365.                 Usage();
  2366.             }
  2367.         }
  2368. #endif
  2369.         else if (!strcasecmp(argv[i], "-nolerp"))
  2370.         {
  2371.              g_lerp_enabled  = false;
  2372.         }
  2373.         else if (!strcasecmp(argv[i], "-chop"))
  2374.         {
  2375.             if (i < argc)
  2376.             {
  2377.                 g_chop = atof(argv[++i]);
  2378.                 if (g_chop < 1)
  2379.                 {
  2380.                     Log("expected value greater than 1 for '-chop'\n");
  2381.                     Usage();
  2382.                 }
  2383.                 if (g_chop < 32)
  2384.                 {
  2385.                     Log("Warning: Chop values below 32 are not recommended.");
  2386.                 }
  2387.             }
  2388.             else
  2389.             {
  2390.                 Usage();
  2391.             }
  2392.         }
  2393.         else if (!strcasecmp(argv[i], "-texchop"))
  2394.         {
  2395.             if (i < argc)
  2396.             {
  2397.                 g_texchop = atof(argv[++i]);
  2398.                 if (g_texchop < 1)
  2399.                 {
  2400.                     Log("expected value greater than 1 for '-texchop'\n");
  2401.                     Usage();
  2402.                 }
  2403.                 if (g_texchop < 32)
  2404.                 {
  2405.                     Log("Warning: texchop values below 16 are not recommended.");
  2406.                 }
  2407.             }
  2408.             else
  2409.             {
  2410.                 Usage();
  2411.             }
  2412.         }
  2413.         else if (!strcasecmp(argv[i], "-notexscale"))
  2414.         {
  2415.             g_texscale = false;
  2416.         }
  2417.         else if (!strcasecmp(argv[i], "-nosubdivide"))
  2418.         {
  2419.             if (i < argc)
  2420.             {
  2421.                 g_subdivide = false;
  2422.             }
  2423.             else
  2424.             {
  2425.                 Usage();
  2426.             }
  2427.         }
  2428.         else if (!strcasecmp(argv[i], "-scale"))
  2429.         {
  2430.             if (i < argc)
  2431.             {
  2432.                  // ------------------------------------------------------------------------
  2433.                 // Changes by Adam Foster - afoster@compsoc.man.ac.uk
  2434.                 // Munge monochrome lightscale into colour one
  2435. #ifdef HLRAD_WHOME
  2436.                 i++;
  2437.                 g_colour_lightscale[0] = (float)atof(argv[i]);
  2438.                 g_colour_lightscale[1] = (float)atof(argv[i]);
  2439.                 g_colour_lightscale[2] = (float)atof(argv[i]);
  2440. #else
  2441.                 g_lightscale = (float)atof(argv[++i]);
  2442. #endif
  2443.                 // ------------------------------------------------------------------------
  2444.             }
  2445.             else
  2446.             {
  2447.                 Usage();
  2448.             }
  2449.         }
  2450.         else if (!strcasecmp(argv[i], "-falloff"))
  2451.         {
  2452.             if (i < argc)
  2453.             {
  2454.                 g_falloff = (float)atoi(argv[++i]);
  2455.                 if ((g_falloff != 1) && (g_falloff != 2))
  2456.                 {
  2457.                     Log("-falloff must be 1 or 2\n");
  2458.                     Usage();
  2459.                 }
  2460.             }
  2461.             else
  2462.             {
  2463.                 Usage();
  2464.             }
  2465.         }
  2466.         else if (!strcasecmp(argv[i], "-fade"))
  2467.         {
  2468.             if (i < argc)
  2469.             {
  2470.                 g_fade = (float)atof(argv[++i]);
  2471.                 if (g_fade < 0.0)
  2472.                 {
  2473.                     Log("-fade must be a positive number\n");
  2474.                     Usage();
  2475.                 }
  2476.             }
  2477.             else
  2478.             {
  2479.                 Usage();
  2480.             }
  2481.         }
  2482.         else if (!strcasecmp(argv[i], "-ambient"))
  2483.         {
  2484.             if (i + 3 < argc)
  2485.             {
  2486.                 g_ambient[0] = (float)atof(argv[++i]) * 128;
  2487.                 g_ambient[1] = (float)atof(argv[++i]) * 128;
  2488.                 g_ambient[2] = (float)atof(argv[++i]) * 128;
  2489.             }
  2490.             else
  2491.             {
  2492.                 Error("expected three color values after '-ambient'\n");
  2493.             }
  2494.         }
  2495.         else if (!strcasecmp(argv[i], "-maxlight"))
  2496.         {
  2497.             if (i < argc)
  2498.             {
  2499.                 g_maxlight = (float)atof(argv[++i]) * 128;
  2500.                 if (g_maxlight <= 0)
  2501.                 {
  2502.                     Log("expected positive value after '-maxlight'\n");
  2503.                     Usage();
  2504.                 }
  2505.             }
  2506.             else
  2507.             {
  2508.                 Usage();
  2509.             }
  2510.         }
  2511.         else if (!strcasecmp(argv[i], "-lights"))
  2512.         {
  2513.             if (i < argc)
  2514.             {
  2515.                 user_lights = argv[++i];
  2516.             }
  2517.             else
  2518.             {
  2519.                 Usage();
  2520.             }
  2521.         }
  2522.         else if (!strcasecmp(argv[i], "-circus"))
  2523.         {
  2524.             g_circus = true;
  2525.         }
  2526.         else if (!strcasecmp(argv[i], "-noskyfix"))
  2527.         {
  2528.             g_sky_lighting_fix = false;
  2529.         }
  2530.         else if (!strcasecmp(argv[i], "-incremental"))
  2531.         {
  2532.             g_incremental = true;
  2533.         }
  2534.         else if (!strcasecmp(argv[i], "-chart"))
  2535.         {
  2536.             g_chart = true;
  2537.         }
  2538.         else if (!strcasecmp(argv[i], "-low"))
  2539.         {
  2540.             g_threadpriority = eThreadPriorityLow;
  2541.         }
  2542.         else if (!strcasecmp(argv[i], "-high"))
  2543.         {
  2544.             g_threadpriority = eThreadPriorityHigh;
  2545.         }
  2546.         else if (!strcasecmp(argv[i], "-nolog"))
  2547.         {
  2548.             g_log = false;
  2549.         }
  2550.         else if (!strcasecmp(argv[i], "-gamma"))
  2551.         {
  2552.             if (i < argc)
  2553.             {
  2554.                 // ------------------------------------------------------------------------
  2555.                 // Changes by Adam Foster - afoster@compsoc.man.ac.uk
  2556.                 // Munge values from original, monochrome gamma into colour gamma
  2557. #ifdef HLRAD_WHOME
  2558.                 i++;
  2559.                 g_colour_qgamma[0] = (float)atof(argv[i]);
  2560.                 g_colour_qgamma[1] = (float)atof(argv[i]);
  2561.                 g_colour_qgamma[2] = (float)atof(argv[i]);
  2562. #else
  2563.                 g_qgamma = (float)atof(argv[++i]);
  2564. #endif
  2565.                 // ------------------------------------------------------------------------
  2566.             }
  2567.             else
  2568.             {
  2569.                 Usage();
  2570.             }
  2571.         }
  2572.         else if (!strcasecmp(argv[i], "-dlight"))
  2573.         {
  2574.             if (i < argc)
  2575.             {
  2576.                 g_dlight_threshold = (float)atof(argv[++i]);
  2577.             }
  2578.             else
  2579.             {
  2580.                 Usage();
  2581.             }
  2582.         }
  2583.         else if (!strcasecmp(argv[i], "-extra"))
  2584.         {
  2585.             g_extra = true;
  2586.         }
  2587.         else if (!strcasecmp(argv[i], "-sky"))
  2588.         {
  2589.             if (i < argc)
  2590.             {
  2591.                 g_indirect_sun = (float)atof(argv[++i]);
  2592.             }
  2593.             else
  2594.             {
  2595.                 Usage();
  2596.             }
  2597.         }
  2598.         else if (!strcasecmp(argv[i], "-smooth"))
  2599.         {
  2600.             if (i < argc)
  2601.             {
  2602.                 g_smoothing_value = atof(argv[++i]);
  2603.             }
  2604.             else
  2605.             {
  2606.                 Usage();
  2607.             }
  2608.         }
  2609.         else if (!strcasecmp(argv[i], "-coring"))
  2610.         {
  2611.             if (i < argc)
  2612.             {
  2613.                 g_coring = (float)atof(argv[++i]);
  2614.             }
  2615.             else
  2616.             {
  2617.                 Usage();
  2618.             }
  2619.         }
  2620.         else if (!strcasecmp(argv[i], "-texdata"))
  2621.         {
  2622.             if (i < argc)
  2623.             {
  2624.                 int             x = atoi(argv[++i]) * 1024;
  2625.  
  2626.                 if (x > g_max_map_miptex)
  2627.                 {
  2628.                     g_max_map_miptex = x;
  2629.                 }
  2630.             }
  2631.             else
  2632.             {
  2633.                 Usage();
  2634.             }
  2635.         }
  2636.         else if (!strcasecmp(argv[i], "-sparse"))
  2637.         {
  2638.             g_method = eMethodSparseVismatrix;
  2639.         }
  2640.         else if (!strcasecmp(argv[i], "-nomatrix"))
  2641.         {
  2642.             g_method = eMethodNoVismatrix;
  2643.         }
  2644.         else if (!strcasecmp(argv[i], "-nopaque"))
  2645.         {
  2646.             g_allow_opaques = false;
  2647.         }
  2648.         else if (!strcasecmp(argv[i], "-dscale"))
  2649.         {
  2650.             if (i < argc)
  2651.             {
  2652.                 g_direct_scale = (float)atof(argv[++i]);
  2653.             }
  2654.             else
  2655.             {
  2656.                 Usage();
  2657.             }
  2658.         }
  2659.  
  2660.         // ------------------------------------------------------------------------
  2661.         // Changes by Adam Foster - afoster@compsoc.man.ac.uk
  2662. #ifdef HLRAD_WHOME
  2663.         else if (!strcasecmp(argv[i], "-colourgamma"))
  2664.         {
  2665.             if (i + 3 < argc)
  2666.             {
  2667.                 g_colour_qgamma[0] = (float)atof(argv[++i]);
  2668.                 g_colour_qgamma[1] = (float)atof(argv[++i]);
  2669.                 g_colour_qgamma[2] = (float)atof(argv[++i]);
  2670.             }
  2671.             else
  2672.             {
  2673.                 Error("expected three color values after '-colourgamma'\n");
  2674.             }
  2675.         }
  2676.         else if (!strcasecmp(argv[i], "-colourscale"))
  2677.         {
  2678.             if (i + 3 < argc)
  2679.             {
  2680.                 g_colour_lightscale[0] = (float)atof(argv[++i]);
  2681.                 g_colour_lightscale[1] = (float)atof(argv[++i]);
  2682.                 g_colour_lightscale[2] = (float)atof(argv[++i]);
  2683.             }
  2684.             else
  2685.             {
  2686.                 Error("expected three color values after '-colourscale'\n");
  2687.             }
  2688.         }
  2689.  
  2690.         else if (!strcasecmp(argv[i], "-colourjitter"))
  2691.         {
  2692.             if (i + 3 < argc)
  2693.             {
  2694.                 g_colour_jitter_hack[0] = (float)atof(argv[++i]);
  2695.                 g_colour_jitter_hack[1] = (float)atof(argv[++i]);
  2696.                 g_colour_jitter_hack[2] = (float)atof(argv[++i]);
  2697.             }
  2698.             else
  2699.             {
  2700.                 Error("expected three color values after '-colourjitter'\n");
  2701.             }
  2702.         }
  2703.         else if (!strcasecmp(argv[i], "-jitter"))
  2704.         {
  2705.             if (i + 3 < argc)
  2706.             {
  2707.                 g_jitter_hack[0] = (float)atof(argv[++i]);
  2708.                 g_jitter_hack[1] = (float)atof(argv[++i]);
  2709.                 g_jitter_hack[2] = (float)atof(argv[++i]);
  2710.             }
  2711.             else
  2712.             {
  2713.                 Error("expected three color values after '-jitter'\n");
  2714.             }
  2715.         }
  2716.  
  2717.         else if (!strcasecmp(argv[i], "-nodiffuse"))
  2718.         {
  2719.             g_diffuse_hack = false;
  2720.         }
  2721.         else if (!strcasecmp(argv[i], "-nospotpoints"))
  2722.         {
  2723.             g_spotlight_hack = false;
  2724.         }
  2725.         else if (!strcasecmp(argv[i], "-softlight"))
  2726.         {
  2727.             if (i + 4 < argc)
  2728.             {
  2729.                 g_softlight_hack[0] = (float)atof(argv[++i]);
  2730.                 g_softlight_hack[1] = (float)atof(argv[++i]);
  2731.                 g_softlight_hack[2] = (float)atof(argv[++i]);
  2732.                 g_softlight_hack_distance = (float)atof(argv[++i]);
  2733.             }
  2734.             else
  2735.             {
  2736.                 Error("expected three color scalers and a distance after '-softlight'\n");
  2737.             }
  2738.         }
  2739. #endif
  2740.         // ------------------------------------------------------------------------
  2741.  
  2742. #ifdef HLRAD_HULLU
  2743.         else if (!strcasecmp(argv[i], "-customshadowwithbounce"))
  2744.         {
  2745.             g_customshadow_with_bouncelight = true;
  2746.         }
  2747.         else if (!strcasecmp(argv[i], "-rgbtransfers"))
  2748.         {
  2749.             g_rgb_transfers = true;
  2750.         }
  2751. #endif
  2752.  
  2753. #ifdef ZHLT_PROGRESSFILE // AJM
  2754.         else if (!strcasecmp(argv[i], "-progressfile"))
  2755.         {
  2756.             if (i < argc)
  2757.             {
  2758.                 g_progressfile = argv[++i];
  2759.             }
  2760.             else
  2761.             {
  2762.                 Log("Error: -progressfile: expected path to progress file following parameter\n");
  2763.                 Usage();
  2764.             }
  2765.         }
  2766. #endif
  2767.  
  2768.         else if (argv[i][0] == '-')
  2769.         {
  2770.             Log("Unknown option \"%s\"\n", argv[i]);
  2771.             Usage();
  2772.         }
  2773.         else if (!mapname_from_arg)
  2774.         {
  2775.             mapname_from_arg = argv[i];
  2776.         }
  2777.         else
  2778.         {
  2779.             Log("Unknown option \"%s\"\n", argv[i]);
  2780.             Usage();
  2781.         }
  2782.     }
  2783.  
  2784.     if (!mapname_from_arg)
  2785.     {
  2786.         Log("No mapname specified\n");
  2787.         Usage();
  2788.     }
  2789.  
  2790.     g_smoothing_threshold = (float)cos(g_smoothing_value * (Q_PI / 180.0));
  2791.  
  2792.     safe_strncpy(g_Mapname, mapname_from_arg, _MAX_PATH);
  2793.     FlipSlashes(g_Mapname);
  2794.     StripExtension(g_Mapname);
  2795.     OpenLog(g_clientid);
  2796.     atexit(CloseLog);
  2797.     ThreadSetDefault();
  2798.     ThreadSetPriority(g_threadpriority);
  2799.     LogStart(argc, argv);
  2800.  
  2801.     CheckForErrorLog();
  2802.  
  2803.     dtexdata_init();
  2804.     atexit(dtexdata_free);
  2805.     // END INIT
  2806.  
  2807.     // BEGIN RAD
  2808.     start = I_FloatTime();
  2809.  
  2810.     // normalise maxlight
  2811.     if (g_maxlight > 255)
  2812.         g_maxlight = 255;
  2813.  
  2814.     strcpy(g_source, mapname_from_arg);
  2815.     StripExtension(g_source);
  2816.     DefaultExtension(g_source, ".bsp");
  2817.     LoadBSPFile(g_source);
  2818.     ParseEntities();
  2819.     Settings();
  2820.     LoadRadFiles(g_Mapname, user_lights, argv[0]);
  2821.     
  2822.     if (!g_visdatasize)
  2823.     {
  2824.         Warning("No vis information, direct lighting only.");
  2825.         g_numbounce = 0;
  2826.         g_ambient[0] = g_ambient[1] = g_ambient[2] = 0.1f;
  2827.     }
  2828.  
  2829.     RadWorld();
  2830.  
  2831.     FreeOpaqueFaceList();
  2832.     FreePatches();
  2833.  
  2834.     if (g_chart)
  2835.         PrintBSPFileSizes();
  2836.  
  2837.     WriteBSPFile(g_source);
  2838.  
  2839.     end = I_FloatTime();
  2840.     LogTimeElapsed(end - start);
  2841.     // END RAD
  2842.  
  2843.     return 0;
  2844. }
  2845.